去年發(fā)生的密碼泄漏事件,我們也對密碼加密做了重新研究。 在篩選加密方法的過程中,發(fā)現(xiàn)了Spring Security 3.1.0版本中提供了新的PasswordEncoder,它的加密方法非常給力!雖然ns同學曾經(jīng)說過“你的網(wǎng)站看起來很安全, 只是因為人家沒精力或者沒興趣搞你...”,但是找到一個好的加密方法,無疑還是會有很大幫助的,至少會延遲破解的時間 說到PasswordEncoder,使用過Spring Security的人應該不會陌生。在3.1.0版本之前,位于org.springframework.security.authentication.encoding包中,輔以一系列的實現(xiàn)類,每個實現(xiàn)類使用了不同的加密方法,有Md4PasswordEncoder、Md5PasswordEncoder、ShaPasswordEncoder、PlaintextPasswordEncoder等。加密方法采用hash+salt方式。 3.0.0版本中PasswordEncoder繼承關(guān)系 在3.1.0及之后的版本,增加了crypto包/模塊,提供了更加強大的對稱加密,生成key,以及密碼加密功能。這個模塊是作為core的一部分存在的,但是對其它任何Spring Security或Spring代碼沒有依賴,也可以單獨作為一個包存在! 3.1.0版本中新的PasswordEncoder繼承關(guān)系 在3.1.0以前的版本中,PasswordEncoder位于 org.springframeword.security.authentication.encoding包中,接口定義如下: - public interface PasswordEncoder{
- String encodePassword(String rawPass,Object salt);
- Boolean isPasswordValid(String encPass,String rawPass,Object salt);
- }
接口中定義了兩個方法,encodePassword()方法是對原始密碼進行加密,采用hash+salt方式,在方法中得提供鹽值(salt)。 isPasswordValid方法是用來驗證密碼是否正確的,得提供三個參數(shù),原始密碼,加密后的密碼以及鹽值(salt)。 在具體加密過程中,可以動態(tài)選擇各種實現(xiàn)類(其實就是各種加密算法),配合salt來進行加密和驗證工作。 缺點就是每次加密和解密都得提供鹽值,那么有兩種方式,一是將鹽值和密碼存在一起,一是使用固定的鹽值。鹽值和密碼存在一起也不是一個好的方案,如果數(shù)據(jù)庫被盜,有了密碼和鹽值,暴力破解會容易一些;而固定的鹽值也不是一個很好的方案。 Spring小組意識到了之前的PasswordEncoder的缺點,于是在3.1.0中推出了新的、更給力的PasswordEncoder,為了向前兼容,不能廢掉PasswordEncoder,于是在另一個包中重新定義了一個PasswordEncoder接口。不過個人愚見,應該在org.springframeword.security.authentication.encoding.PasswordEncoder接口上增加@Deprecated 而在Spring-Security 3.1.0 版本之后,Spring-security-crypto模塊中的password包提供了更給力的加密密碼的支持,這個包中也有PasswordEncoder接口,接口定義如下。 - Public interface PasswordEncoder{
- String encode(String rawPassword);
- Boolean matches(String rawPassword,String encodedPassword);
- }
定義了兩個方法,encode方法是對方法加密,而match方法是用來驗證密碼和加密后密碼是否一致的,如果一致則返回true。和authentication.encoding包中的PasswordEncoder接口相比,簡化了許多。 位于org.springframeword.security.crypto.password包中的 StandardPasswordEncoder類,是PasswordEncoder接口的(唯一)一個實現(xiàn)類,是本文所述加密方法的核心。它采用SHA-256算法,迭代1024次,使用一個密鑰(site-wide secret)以及8位隨機鹽對原密碼進行加密。 隨機鹽確保相同的密碼使用多次時,產(chǎn)生的哈希都不同; 密鑰應該與密碼區(qū)別開來存放,加密時使用一個密鑰即可;對hash算法迭代執(zhí)行1024次增強了安全性,使暴力破解變得更困難些。 和上一個版本的PasswordEncoder比較,好處顯而易見:鹽值不用用戶提供,每次隨機生成;多重加密————迭代SHA算法+密鑰+隨機鹽來對密碼加密,大大增加密碼破解難度。 簡單封裝一下: - public class EncryptUtil {
- //從配置文件中獲得
- private static final String SITE_WIDE_SECRET = "beibei";
- private static final PasswordEncoder encoder = new StandardPasswordEncoder(
- SITE_WIDE_SECRET);
-
- public static String encrypt(String rawPassword) {
- return encoder.encode(rawPassword);
- }
-
- public static boolean match(String rawPassword, String password) {
- return encoder.matches(rawPassword, password);
- }
- }
從配置文件中獲得密鑰(SITE_WIDE_SECRET),使用static的PasswordEncoder,保證只用一個實例來加密與 匹配。 加密后得到的密碼是80位,霸氣十足。 - public static void main(String[] args) {
- System.out.println(EncryptUtil.encrypt("test"));
- System.out.println(EncryptUtil.encrypt("test"));
- System.out.println(EncryptUtil.encrypt("test"));
- }
-
引用
b84e62f1d332154e1db9da86c1ec30ee86c43f0307fd1c4b06873167eb08ca674bbf72cfe2a99b5d
05b78338cb2c275e471533b05eff31979f5e4df9695ab72eb55cfe3abd92a7d581f250fc9d37d801
aba3493a7cd4e646a1ea33b2a1b074b03899b5e76618bfea70542fa337e286cb2ac27bde4f4be903
本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點擊舉報。