Spring Security(三十三):10.3 Password Encoding

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. java

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.spring

在某種意義上,散列是「單向的」,即在給定散列值的狀況下得到原始輸入是很是困難的(其實是不可能的),或者實際上任何可能產生該散列值的輸入。此屬性使哈希值對於身份驗證很是有用。它們能夠存儲在您的用戶數據庫中,做爲明文密碼的替代方法,即便這些值被泄露,它們也不會當即顯示可用於登陸的密碼。請注意,這也意味着您沒法在編碼後恢復密碼。

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. promise

當身份驗證提供程序(例如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方法。
相關文章
相關標籤/搜索