Spring Security 中的 BCryptPasswordEncoder加密、驗證策略
首先明確一點,那就是 BCrypt 演算法是一種 單向Hash加密演算法。
演算法 | 特點 | 有效破解方式 | 破解難度 | 其它 |
---|---|---|---|---|
對稱加密 | 可以解密出明文 | 獲取金鑰 | 中 | 需要確保金鑰不被洩露 |
單向Hash | 不可解密 | 碰撞/彩虹表 | 中 | 可以通過加鹽和多次hash來提高安全性,確保鹽不被洩漏 |
Pbkdf2 | 不可解密 | 暫無 | 難 | 需要設定合理的引數 |
加密過程
直接上程式碼:以 spring-security-core-5.3.4.RELEASE-sources.jar
包中為例,在 BCryptPasswordEncoder.java
中,可以清晰的看到,有多個構造引數,構造引數重,有3個主要的引數:
BCryptVersion
加密演算法的版本,預設 $2A,除此之外可選的有$2Y和$2B;strength
個人理解的是單向hash的次數,預設值是10,可選4打31位;random
安全的隨機數生成器,不指定的話,就是 BCrypt.gensalt(version.getVersion(), strength) 方法來生成
上面這些都可以不用指定,有預設值。加密呼叫的方法是org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder#encode
。具體原始碼如下:
public String encode(CharSequence rawPassword) {
if (rawPassword == null) {
throw new IllegalArgumentException("rawPassword cannot be null");
}
String salt;
if (random != null) {
salt = BCrypt.gensalt(version.getVersion(), strength, random);
} else {
salt = BCrypt.gensalt(version.getVersion(), strength);
}
return BCrypt.hashpw(rawPassword.toString(), salt);
}
其中可以看出,關鍵的步驟在 BCrypt.hashpw(rawPassword.toString(), salt);
中。感興趣具體的實現,可以再去對照原始碼進行分析。筆者更在意它生成後的儲存格式,加密後的祕文格式如下:
通常,這部分格式也是最終程式碼入庫的部分。
解密過程
解密的思路,從已經加密後的祕文中,取出鹽值,然後同使用者輸入的明文,進行BCrypt演算法加密。將加密後的資料同資料庫中儲存的資料進行比較,如果相同,則認為密碼輸入正確,否則校驗失敗。具體的org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder#matches
原始碼如下:
public boolean matches(CharSequence rawPassword, String encodedPassword) {
if (rawPassword == null) {
throw new IllegalArgumentException("rawPassword cannot be null");
}
if (encodedPassword == null || encodedPassword.length() == 0) {
logger.warn("Empty encoded password");
return false;
}
if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
logger.warn("Encoded password does not look like BCrypt");
return false;
}
// 將明文同已經經過加鹽+BCrypt演算法加密後祕文進行比較
return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
}
/**
* Check that a password (as a byte array) matches a previously hashed
* one
* @param passwordb the password to verify, as a byte array
* @param hashed the previously-hashed password
* @return true if the passwords match, false otherwise
* @since 5.3
*/
public static boolean checkpw(byte[] passwordb, String hashed) {
return equalsNoEarlyReturn(hashed, hashpw(passwordb, hashed));
}
個人感覺講述的比較清晰資料
參考資料:
相關文章
- Spring Security 中的 BCryptPasswordEncoderSpring
- Spring Security 6中使用PKCE實現身份驗證Spring
- 詳解Spring Security的HttpBasic登入驗證模式SpringHTTP模式
- 自定義Spring Security的身份驗證失敗處理Spring
- [譯] 學習 Spring Security(五):重發驗證郵件Spring
- Spring security(四)-spring boot +spring security簡訊認證+redis整合Spring BootRedis
- Spring Security原始碼分析一:Spring Security認證過程Spring原始碼
- Spring Security認證提供程式Spring
- Spring Security OAuth2之resource_id配置與驗證SpringOAuth
- Spring認證_什麼是Spring Security?Spring
- [收藏]Spring Security中的ACLSpring
- Spring Security Oauth2.0 實現簡訊驗證碼登入SpringOAuth
- Spring security(三)---認證過程Spring
- spring security許可權認證Spring
- Spring Security認證器實現Spring
- Spring Security 一鍵接入驗證碼登入和小程式登入Spring
- spring security 認證原始碼跟蹤Spring原始碼
- spring security 自定義認證登入Spring
- SpringBoot + Spring Security 學習筆記(三)實現圖片驗證碼認證Spring Boot筆記
- 策略模式下表單驗證模式
- 線上Bcrypt加密、驗證工具加密
- Spring Boot + Security + JWT 實現Token驗證+多Provider——登入系統Spring BootJWTIDE
- Spring Security 6.3基於JWT身份驗證與授權開源專案SpringJWT
- 【認證與授權】Spring Security的授權流程Spring
- 登入邏輯中的驗證碼顯示策略優化優化
- 五、Spring Boot整合Spring Security之認證流程2Spring Boot
- Spring Security系列之認證過程(六)Spring
- 【Spring Security】實現多種認證方式Spring
- Spring Security中AuthorizationManager簡介Spring
- Spring Security 如何新增登入驗證碼?鬆哥手把手教你給微人事新增登入驗證碼Spring
- Spring Security 實戰乾貨:從零手寫一個驗證碼登入Spring
- 為listener增加密碼驗證加密密碼
- 【認證與授權】Spring Security系列之認證流程解析Spring
- spirng-boot中,基於既有的token驗證方式,利用spring-security實現許可權系統bootSpring
- spring security oauth2 搭建認證中心demoSpringOAuth
- 產品設計中收不到驗證碼解決策略
- Spring Security 實戰乾貨:圖解Spring Security中的Servlet過濾器體系Spring圖解Servlet過濾器
- HTTPS加密過程和TLS證書驗證HTTP加密TLS