1. 程式人生 > >Spring Security(三十三):10.3 Password Encoding

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. 

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方法。