使用spring?security?BCryptPasswordEncoder接入系統(tǒng)
spring security BCryptPasswordEncoder接入系統(tǒng)
通常情況下,在新系統(tǒng)中使用BCrypt加密不需要考慮太多,但老系統(tǒng)由于存在大量舊數(shù)據(jù),草率接入會導(dǎo)致老用戶無法登錄,這種情況該怎么解決?
很簡單,我們自己實現(xiàn)一個PasswordEncoder 并繼承BCrpytPasswordEncoder即可。
@Component public class MyPasswordEncoder extends BCryptPasswordEncoder { private final Log logger = LogFactory.getLog(this.getClass()); // BCrypt 密文的正則表達式 private Pattern BCRYPT_PATTERN = Pattern.compile("\\A\\$2(a|y|b)?\\$(\\d\\d)\\$[./0-9A-Za-z]{53}"); @Override public boolean matches(CharSequence rawPassword, String encodedPassword) { if (rawPassword == null) { throw new IllegalArgumentException("rawPassword cannot be null"); } else if (encodedPassword != null && encodedPassword.length() != 0) { if (!this.BCRYPT_PATTERN.matcher(encodedPassword).matches()) { // TODO 如果密碼不是BCrypt 密文 do something return ...; } else { return BCrypt.checkpw(rawPassword.toString(), encodedPassword); } } else { this.logger.warn("Empty encoded password"); return false; } } }
在這個PasswordEncoder中,只有當密碼不是BCrypt密文時,才啟用自定義的匹配邏輯,
其余還是沿用原來的方案,即可輕松達到兼容的目的。
再進一步,如果我們不僅想要兼容,還想將不安全的舊密碼無縫修改成BCrypt密文,該如何操作呢?這是個很好的問題。
如果舊密碼都是未經(jīng)任何加密的明文,也許“跑庫”修改是非常好的一種選擇,但并非所有系統(tǒng)都有這么理想的狀態(tài)。
假如舊密碼都是被散列加密過的,那么可以使用下列兩種選擇:
1.使用增量更新的方法。當用戶輸入的密碼正確時,判斷數(shù)據(jù)庫中的密碼是否為BCrypt密文,如果不是,則嘗試使用用戶輸入的密碼重新生成BCrpyt密文并寫回數(shù)據(jù)庫。
2.以舊的加密方案作為基礎(chǔ)接入BCrpyt加密,eg: 舊的方案是MD5加密,即數(shù)據(jù)庫中的所有密碼都是MD5形式的密碼,那么直接把這些密碼當作明文,先“跑庫”生成BCrypt密文,再使用encode和matches兩個方法在執(zhí)行BCrypt加密之前都先用MD5運算一遍即可。
spring security的BCryptPasswordEncoder問題
早些年,那會把一個老項目的登錄模塊重構(gòu),從Shiro轉(zhuǎn)Spring Security,那時候快速換完后沒多看,最近又在公司做類似同樣的操作,給一個老項目加上Spring Security。所以我決定簡單寫點什么。相信用過Spring Security的伙伴們,應(yīng)該對這個BCryptPasswordEncoder 都有好奇。為啥好奇, 這個家伙的加密方法encode每次生成的密后密碼都不一樣,但是校驗方法matches卻能準確地去檢驗匹配。
不多說,現(xiàn)在一起來看看。
1. 先看encode這個方法
不用細看,我們看兩個關(guān)鍵信息:
- BCrypt.gensalt
- BCrypt.hashpw
沒錯,這個加密算法其實是 強哈希+鹽+密鑰(默認用密碼)。 因為使用到了哈希,所以是不可逆。
這也就能初步明白matches 為什么只能用來做校驗匹配,而不是直接解密。 這點意味著就算你加密后的密碼泄露了,別人想直接得到明文幾乎是不可能的。
接下來,有必要看hashpw么,放到下面一起看。
2. 接下來看matches這個方法
關(guān)注點:
BCrypt.checkpw(rawPassword.toString(), encodedPassword);
沒錯,因為哈希無法逆操作,所以匹配過程中也是用了hashpw 。 可以看到了checkpw這個方法,我們傳入的密文其實命名已經(jīng)是 hashed ,沒錯,這個密文就是一個帶有鹽值的哈希。
hashpw 里面,前面一大堆都是在校驗密文格式對不對,因為可以看到我們的加密后得到的密文格式是不是有點像?
符合格式了就開始截?。?/p>
明文有了,鹽值也有了,那么匹配就跟我們一般接口的sign認證一樣了。
簡單的了解就到此吧。
PS: 這個BCryptPasswordEncoder加密&校驗方法當個工具類,導(dǎo)包+啟動類屏蔽Security默認自動裝配,用起來也是可以的。
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
java操作gaussDB數(shù)據(jù)庫的實現(xiàn)示例
本文主要介紹了java操作gaussDB數(shù)據(jù)庫的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07java中 spring 定時任務(wù) 實現(xiàn)代碼
java中 spring 定時任務(wù) 實現(xiàn)代碼,需要的朋友可以參考一下2013-03-03spring中@ControllerAdvice 注解的使用
@ControllerAdvice注解是Spring3.2中新增的注解,主要用于Controller的全局配置,本文就來介紹一下spring中@ControllerAdvice 注解的使用,感興趣的可以了解一下2024-09-09Tree組件實現(xiàn)支持50W數(shù)據(jù)方法剖析
這篇文章主要為大家介紹了Tree組件實現(xiàn)支持50W數(shù)據(jù)的方法剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08