如何基于Security框架兼容多套用戶密碼加密方式

mark

一、說明

當(dāng)已上線的系統(tǒng)存在使用其他的加密方式加密的密碼數(shù)據(jù),并且密碼 不可逆 時,而新的數(shù)據(jù)采用了其他的加密方式,則需要同時兼容多種加密方式的密碼校驗。

例如下列幾種情況:

  1. 舊系統(tǒng)用戶的密碼采用了 MD5 的加密方式,而升級框架后的新系統(tǒng)則采用 BCrypt 的加密方式;
  2. 當(dāng)割接歷史數(shù)據(jù)后會存在用戶表中密碼的 加密方式不統(tǒng)一 的問題,歷史數(shù)據(jù)為 MD5 新數(shù)據(jù)為 BCrypt;
  3. 所以需要系統(tǒng)支持同時兼容多種加密方式的密碼校驗。

本文分享基于Security的PasswordEncoder來實現(xiàn)兼容多套用戶密碼加密方式。

?

二、DelegatingPasswordEncoder

在 spring Security 5.0之后,默認的密碼加密方案其實是 DelegatingPasswordEncoder 它是一個代理類,而并非一種全新的密碼加密方案,可以用來代理多種不同的密碼加密方案。

?
代碼參考

Map<String, PasswordEncoder> encoders = new HashMap<>();
encoders.put("bcrypt", new BCryptPasswordEncoder());
encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder());
encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder());
encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5"));
encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1"));
encoders.put("SHA-256", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256"));
encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder());
encoders.put("argon2", new Argon2PasswordEncoder());
encoders.put("SM3", new SM3PasswordEncoder());

Assert.isTrue(encoders.containsKey(encodingId), encodingId + " is not found in idToPasswordEncoder");

DelegatingPasswordEncoder delegatingPasswordEncoder = new DelegatingPasswordEncoder(encodingId, encoders);
delegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(encoders.get(encodingId));
return delegatingPasswordEncoder;

自動會根據(jù)數(shù)據(jù)的 encodingId 來使用對應(yīng)的編譯器處理密碼

?

三、如何使用

3.1. 修改歷史密碼數(shù)據(jù)

修改舊的密碼數(shù)據(jù)的值,添加前綴標(biāo)識 encodingId 格式如下:

  • 無鹽值
{encodingId}密碼

例如源密碼為:$2a$10$EgTOU7PMe.3jaMwFsumdweJcnY3TsTqyuJEdSaSKxdgwYchAwUJ1C

則修改為:
{bcrypt}$2a$10$EgTOU7PMe.3jaMwFsumdweJcnY3TsTqyuJEdSaSKxdgwYchAwUJ1C
  • 有鹽值
{encodingId}{salt}密碼

例如源密碼為:
0758f7131c6c95c8e3df05e1ac50214c

則修改為:
{MD5}{5Hstj}0758f7131c6c95c8e3df05e1ac50214c

encodingId 的值可參考 PwdEncoderUtil

如下圖所示:

file

3條記錄中,前兩條為原有的歷史記錄使用的是 MD5 的加密算法,然后新插入的數(shù)據(jù)使用的為 bcrypt 的加密算法,分別使用不同的前綴標(biāo)識 encodingId

?

3.2. 配置 PasswordEncoder 對象

使用 DelegatingPasswordEncoder 類來定義 PasswordEncoder 并且指定默認加密方式為 bcrypt

@Bean
public PasswordEncoder passwordEncoder() {
   return PwdEncoderUtil.getDelegatingPasswordEncoder("bcrypt");
}

以下兩種情況下都是使用默認的加密方式:

  1. 使用 encode 方法加密數(shù)據(jù)。
  2. 使用 matches 方法對比密文和原文時,密文沒有 encodingId 標(biāo)識。

?

3.3. 參考代碼

https://gitee.com/zlt2000/microservices-platform/blob/master/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/PwdEncoderUtil.java

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容