Spring Security’s PasswordEncoder interface is used to support the use of passwords which are encoded in some way in persistent storage. You should never store passwords in plain text. Always use a one-way password hashing algorithm such as bcrypt which uses a built-in salt value which is different for each stored password. Do not use a plain hash function such as MD5 or SHA, or even a salted version. Bcrypt is deliberately designed to be slow and to hinder offline password cracking, whereas standard hash algorithms are fast and can easily be used to test thousands of passwords in parallel on custom hardware. You might think this doesn’t apply to you since your password database is secure and offline attacks aren’t a risk.

Spring Security的PasswordEncoder接口用于支持使用在持久存储中以某种方式编码的密码。您绝不应以纯文本格式存储密码。始终使用单向密码散列算法,例如bcrypt,它使用内置的salt值,该值对于每个存储的密码是不同的。不要使用普通的哈希函数,如MD5或SHA,甚至是盐渍版本。 Bcrypt被故意设计为缓慢并阻碍脱机密码破解,而标准哈希算法很快,可以很容易地用于在自定义硬件上并行测试数千个密码。您可能认为这不适用于您,因为您的密码数据库是安全的,并且脱机攻击不存在风险。
 
If so, do some research and read up on all the high-profile sites which have been compromised in this way and have been pilloried for storing their passwords insecurely. It’s best to be on the safe side. Using org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" is a good choice for security. There are also compatible implementations in other common programming languages so it a good choice for interoperability too.
如果是这样的话,做一些研究并阅读所有以这种方式受到损害的高知名度的网站,并因为不安全地存储密码而受到嘲笑。最好是安全起见。使用org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder“是一个很好的安全选择。在其他常见的编程语言中也有兼容的实现,因此它也是互操作性的一个很好的选择。
 
If you are using a legacy system which already has hashed passwords, then you will need to use an encoder which matches your current algorithm, at least until you can migrate your users to a more secure scheme (usually this will involve asking the user to set a new password, since hashes are irreversible). Spring Security has a package containing legacy password encoding implementation, namely, org.springframework.security.authentication.encoding. The DaoAuthenticationProvider can be injected with either the new or legacy PasswordEncoder types.
如果您使用的是已经具有散列密码的旧系统,那么您将需要使用与当前算法匹配的编码器,至少在您将用户迁移到更安全的方案之前(通常这将涉及要求用户设置)一个新密码,因为哈希是不可逆转的)。 Spring Security有一个包含传统密码编码实现的包,即org.springframework.security.authentication.encoding。可以使用新的或旧的PasswordEncoder类型注入DaoAuthenticationProvider。

10.3.1 What is a hash?

Password hashing is not unique to Spring Security but is a common source of confusion for users who are not familiar with the concept. A hash (or digest) algorithm is a one-way function which produces a piece of fixed-length output data (the hash) from some input data, such as a password. As an example, the MD5 hash of the string "password" (in hexadecimal) is

密码散列并非Spring Security独有,但却是不熟悉该概念的用户常见的混淆源。散列(或摘要)算法是单向函数,其从一些输入数据(例如密码)产生一段固定长度的输出数据(散列)。例如,字符串“password”(十六进制)的MD5哈希值是
 
5f4dcc3b5aa765d61d8327deb882cf99

A hash is "one-way" in the sense that it is very difficult (effectively impossible) to obtain the original input given the hash value, or indeed any possible input which would produce that hash value. This property makes hash values very useful for authentication purposes. They can be stored in your user database as an alternative to plaintext passwords and even if the values are compromised they do not immediately reveal a password which can be used to login. Note that this also means you have no way of recovering the password once it is encoded.

在某种意义上,散列是“单向的”,即在给定散列值的情况下获得原始输入是非常困难的(实际上是不可能的),或者实际上任何可能产生该散列值的输入。此属性使哈希值对于身份验证非常有用。它们可以存储在您的用户数据库中,作为明文密码的替代方法,即使这些值被泄露,它们也不会立即显示可用于登录的密码。请注意,这也意味着您无法在编码后恢复密码。

10.3.2 Adding Salt to a Hash

One potential problem with the use of password hashes that it is relatively easy to get round the one-way property of the hash if a common word is used for the input. People tend to choose similar passwords and huge dictionaries of these from previously hacked sites are available online. For example, if you search for the hash value 5f4dcc3b5aa765d61d8327deb882cf99 using google, you will quickly find the original word "password". In a similar way, an attacker can build a dictionary of hashes from a standard word list and use this to lookup the original password.

使用密码哈希的一个潜在问题是,如果将常用字用于输入,则相对容易绕过哈希的单向属性。人们倾向于选择类似的密码,并且可以在线获取以前被黑客攻击的网站中的大量字典。例如,如果使用谷歌搜索哈希值5f4dcc3b5aa765d61d8327deb882cf99,您将很快找到原始单词“password”。以类似的方式,攻击者可以从标准单词列表构建哈希字典,并使用它来查找原始密码。
 
One way to help prevent this is to have a suitably strong password policy to try to prevent common words from being used. Another is to use a "salt" when calculating the hashes. This is an additional string of known data for each user which is combined with the password before calculating the hash. Ideally the data should be as random as possible, but in practice any salt value is usually preferable to none. Using a salt means that an attacker has to build a separate dictionary of hashes for each salt value, making the attack more complicated (but not impossible).
一种有助于防止这种情况的方法是使用适当强大的密码策略来尝试防止使用常用词。另一种是在计算哈希时使用“盐”。这是每个用户的附加字符串,在计算哈希值之前与密码组合。理想情况下,数据应尽可能随机,但实际上任何盐值通常都优于无。使用salt意味着攻击者必须为每个salt值构建一个单独的哈希字典,使攻击更加复杂(但并非不可能)。
 
Bcrypt automatically generates a random salt value for each password when it is encoded, and stores it in the bcrypt string in a standard format.
Bcrypt在编码时自动为每个密码生成一个随机盐值,并以标准格式将其存储在bcrypt字符串中。
 

The legacy approach to handling salt was to inject a SaltSource into the DaoAuthenticationProvider, which would obtain a salt value for a particular user and pass it to the PasswordEncoder. Using bcrypt means you don’t have worry about the details of salt handling (such as where the value is stored), as it is all done internally. So we’d strongly recommend you use bcrypt unless you already have a system in place which stores the salt separately.

处理salt的传统方法是将SaltSource注入DaoAuthenticationProvider,它将获取特定用户的salt值并将其传递给PasswordEncoder。使用bcrypt意味着您不必担心盐处理的细节(例如存储值的位置),因为它都是在内部完成的。所以我们强烈建议您使用bcrypt,除非您已经有一个系统可以单独存储盐。
 

10.3.3 Hashing and Authentication

When an authentication provider (such as Spring Security’s DaoAuthenticationProvider) needs to check the password in a submitted authentication request against the known value for a user, and the stored password is encoded in some way, then the submitted value must be encoded using exactly the same algorithm. It’s up to you to check that these are compatible as Spring Security has no control over the persistent values. If you add password hashing to your authentication configuration in Spring Security, and your database contains plaintext passwords, then there is no way authentication can succeed. Even if you are aware that your database is using MD5 to encode the passwords, for example, and your application is configured to use Spring Security’s Md5PasswordEncoder, there are still things that can go wrong.

当身份验证提供程序(例如Spring Security的DaoAuthenticationProvider)需要针对用户的已知值检查提交的身份验证请求中的密码,并且以某种方式对存储的密码进行编码时,必须使用完全相同的方式对提交的值进行编码算法。由您决定这些是否兼容,因为Spring Security无法控制持久值。如果在Spring Security中为您的身份验证配置添加密码哈希,并且您的数据库包含明文密码,那么身份验证就无法成功。例如,即使您知道数据库使用MD5对密码进行编码,并且您的应用程序配置为使用Spring Security的Md5PasswordEncoder,仍然可能出现问题。
 
The database may have the passwords encoded in Base 64, for example while the encoder is using hexadecimal strings (the default). Alternatively your database may be using upper-case while the output from the encoder is lower-case. Make sure you write a test to check the output from your configured password encoder with a known password and salt combination and check that it matches the database value before going further and attempting to authenticate through your application. Using a standard like bcrypt will avoid these issues.
数据库可能具有以Base 64编码的密码,例如,当编码器使用十六进制字符串(默认值)时。或者,您的数据库可能使用大写,而编码器的输出是小写的。确保编写测试以使用已知密码和salt组合检查已配置密码编码器的输出,并在进一步尝试通过应用程序进行身份验证之前检查它是否与数据库值匹配。使用像bcrypt这样的标准可以避免这些问题。
 
If you want to generate encoded passwords directly in Java for storage in your user database, then you can use the encode method on the PasswordEncoder.
如果要直接在Java中生成编码密码以存储在用户数据库中,则可以在PasswordEncoder上使用encode方法。
 

Spring Security(三十三):10.3 Password Encoding的更多相关文章

  1. 使用Spring Security Oauth2完成RESTful服务password认证的过程

            摘要:Spring Security与Oauth2整合步骤中详细描述了使用过程,但它对于入门者有些重量级,比如将用户信息.ClientDetails.token存入数据库而非内存.配置 ...

  2. Spring Security(三) —— 核心配置解读

    摘要: 原创出处 https://www.cnkirito.moe/spring-security-3/ 「老徐」欢迎转载,保留摘要,谢谢! 3 核心配置解读 上一篇文章<Spring Secu ...

  3. Spring Security(十三):5.2 HttpSecurity

    Thus far our WebSecurityConfig only contains information about how to authenticate our users. How do ...

  4. Spring Security三种认证

    Spring Security: 1.用户名+密码认证 2.手机号+短信认证 Spring Social: 1.第三方认证, QQ登录等 Spring Security OAuth: 1.把认证之后的 ...

  5. spring security 学习文档

    web service Prepared by:   Sea                                                                       ...

  6. SpringBoot集成Spring Security入门体验

    一.前言 Spring Security 和 Apache Shiro 都是安全框架,为Java应用程序提供身份认证和授权. 二者区别 Spring Security:重量级安全框架 Apache S ...

  7. Spring Security(七):2.4 Getting Spring Security

    You can get hold of Spring Security in several ways. You can download a packaged distribution from t ...

  8. Spring Security(三十二):10. Core Services

    Now that we have a high-level overview of the Spring Security architecture and its core classes, let ...

  9. Spring Security(三十四):10.4 Jackson Support

    Spring Security has added Jackson Support for persisting Spring Security related classes. This can i ...

随机推荐

  1. Python实战171201筛选数据

    Python应用:网络编程,系统网络运维,3D游戏开发,图形界面开发,科学与数字计算,web后端. 对着慕课的练习,果然慕课的实战也是差距很大-------centos7 -Python3.6.3 筛 ...

  2. 设计模式总结篇系列:建造者模式(Builder)

    关于建造者模式网上有很多文章,也有些不同的理解.在此结合网上其他文章对建造者模式进行总结. 总体说来,建造者模式适合于一个具有较多的零件(属性)的产品(对象)的创建过程.根据产品创建过程中零件的构造是 ...

  3. 超级账本fabric原理之gossip详解

    Goosip协议 去中心化.容错和最终一致性的算法 信息达到同步的最优时间:log(N). 功能: 节点发现 数据广播 gossip中有三种基本的操作: push - A节点将数据(key,value ...

  4. JavaScript 中,定义函数时用 var foo = function () {} 和 function foo() {}有什么区别?

    对于新手来说(本人也是新手-_-!),好像var foo = function () {} 和 function foo(){}并没有什么区别,意识里可能就认为就是两种不同的写法而已.但是,通过网上查 ...

  5. Aspose.Word邮件合并之自定义数据源

    Aspose.Word在进行邮件合并时,默认的几个重载方法对Database支持比较友好,但是也可以通过自定义数据源来实现从集合或者对象中返回数据进行邮件合并. 自定义数据源主要是通过实现IMailM ...

  6. [PHP]命令执行函数的区别

    <?php $cmd="ps aux|grep php-fpm"; $res=exec($cmd,$o); var_dump($o);//数组形式返回,每行一个元素 var_ ...

  7. js中的new()到底做了些什么??

    要创建 Person 的新实例,必须使用 new 操作符.以这种方式调用构造函数实际上会经历以下 4个步骤:(1) 创建一个新对象:(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新 ...

  8. Android 应用的逆向和审计

    Android 应用程序拆解 Android 应用程序是在开发应用程序时创建的数据和资源文件的归档文件. Android 应用程序的扩展名是.apk,意思是应用程序包,在大多数情况下包括以下文件和文件 ...

  9. 等价路由在路由器和CE交换机上默认的行为是不同的,路由器总是走第一个下一跳,CE交换机是逐包。

    结论: 1.在eNSP中实验,路由器和CE交换机对于等价路由的默认转发行为是不同的, 路由器:默认是基于流的转发形态,更准确的来讲,ping两个不同的下一跳,都是走等价路由的第一个路由,不走第二条路由 ...

  10. (简单)华为荣耀9i LLD-AL20的Usb调试模式在哪里开启的方法

    每当我们使用pc通过数据线连接上安卓手机的时候,如果手机没有开启Usb开发者调试模式,pc则没法成功检测到我们的手机,有时,我们使用的一些功能较好的应用如以前我们使用的一个应用引号精灵,老版本就需要开 ...