spring security BCryptPasswordEncoder加密解密,不錯的隨機鹽,不錯的加密解密方法


項目中用這個加密感覺不錯啊,推薦:

1.先大體看看,了解一下

淺談使用springsecurity中的BCryptPasswordEncoder方法對密碼進行加密(encode)與密碼匹配(matches)

spring security中的BCryptPasswordEncoder方法采用SHA-256 +隨機鹽+密鑰對密碼進行加密。SHA系列是Hash算法,不是加密算法,使用加密算法意味着可以解密(這個與編碼/解碼一樣),但是采用Hash處理,其過程是不可逆的。

(1)加密(encode):注冊用戶時,使用SHA-256+隨機鹽+密鑰把用戶輸入的密碼進行hash處理,得到密碼的hash值,然后將其存入數據庫中。

(2)密碼匹配(matches):用戶登錄時,密碼匹配階段並沒有進行密碼解密(因為密碼經過Hash處理,是不可逆的),而是使用相同的算法把用戶輸入的密碼進行hash處理,得到密碼的hash值,然后將其與從數據庫中查詢到的密碼hash值進行比較。如果兩者相同,說明用戶輸入的密碼正確。

這正是為什么處理密碼時要用hash算法,而不用加密算法。因為這樣處理即使數據庫泄漏,黑客也很難破解密碼(破解密碼只能用彩虹表)。

 

任何應用考慮到安全,絕不能明文的方式保存密碼。密碼應該通過哈希算法進行加密。有很多標准的算法比如SHA或者MD5,結合salt(鹽)是一個不錯的選擇。 Spring Security 提供了BCryptPasswordEncoder類,實現Spring的PasswordEncoder接口使用BCrypt強哈希方法來加密密碼。

BCrypt強哈希方法 每次加密的結果都不一樣。

---------------------------------------------------------------------------------------------------------------

2.這里BCryptPasswordEncoder看看他怎么用:

作者:知乎用戶
鏈接:https://www.zhihu.com/question/54720851/answer/288322108
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
 

學習到這一塊,查看了一些源碼。以BCryptPasswordEncoder為例

public class BCryptPasswordEncoderTest {
    public static void main(String[] args) {
        String pass = "admin";
        BCryptPasswordEncoder bcryptPasswordEncoder = new BCryptPasswordEncoder();
        String hashPass = bcryptPasswordEncoder.encode(pass);
        System.out.println(hashPass);

        boolean f = bcryptPasswordEncoder.matches("admin",hashPass);
        System.out.println(f);

    }
}

可以看到,每次輸出的hashPass 都不一樣,
但是最終的f都為 true,即匹配成功。

查看代碼,可以看到,其實每次的隨機鹽,都保存在hashPass中。

在進行matchs進行比較時,調用BCrypt 的String hashpw(String password, String salt)

方法。兩個參數即”admin“和 hashPass

//******BCrypt.java******salt即取出要比較的DB中的密碼*******
real_salt = salt.substring(off + 3, off + 25);
try {
// ***************************************************
    passwordb = (password + (minor >= 'a' ? "\000" : "")).getBytes("UTF-8");
}
catch (UnsupportedEncodingException uee) {}
saltb = decode_base64(real_salt, BCRYPT_SALT_LEN);
B = new BCrypt();
hashed = B.crypt_raw(passwordb, saltb, rounds);

假定一次hashPass為:$2a$10$AxafsyVqK51p.s9WAEYWYeIY9TKEoG83LTEOSB3KUkoLtGsBKhCwe

隨機鹽即為 AxafsyVqK51p.s9WAEYWYe

(salt = BCrypt.gensalt();中有描述)

可見,隨機鹽(AxafsyVqK51p.s9WAEYWYe),會在比較的時候,重新被取出。

即,加密的hashPass中,前部分已經包含了鹽信息。

--------------------------------------------------------------------------------------------------------------------

3.在springcloud中整合,下面說的也不清楚。。。。。

好了廢話不多說,就看怎么整合吧。。

1. 修改 WebSecurityConfig

    @Autowired
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserService).passwordEncoder(new BCryptPasswordEncoder());
    }
  •  

這樣配置就好了。但是關於怎么初始化密碼呢,和注冊用戶的時候怎么給密碼加密呢?

  public SysUser create(User u user){
        //進行加密
        BCryptPasswordEncoder encoder =new BCryptPasswordEncoder();
        sysUser.setPassword(encoder.encode(user.getRawPassword().trim()));
        userDao.create(user);
    return sysUser;
  •  

雖然每次 BCryptPasswordEncoder 的 encoder 結果都不一樣,但是存貯其中一次加密結果 也能夠驗證成功

2019/06/14更新

這個在新版本中是的結果不是上面知乎演示的結果,新版中是按照一列類規則進行驗證的,加密結果前面並不包含鹽

原文地址:https://blog.csdn.net/lidew521/article/details/82463736


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM