一、阐明
当已上线的零碎存在应用其余的加密形式加密的明码数据,并且明码 不可逆 时,而新的数据采纳了其余的加密形式,则须要同时兼容多种加密形式的明码校验。
例如下列几种状况:
- 旧零碎用户的明码采纳了 MD5 的加密形式,而降级框架后的新零碎则采纳 BCrypt 的加密形式;
- 当割接历史数据后会存在用户表中明码的 加密形式不对立 的问题,历史数据为 MD5 新数据为 BCrypt;
- 所以须要零碎反对同时兼容多种加密形式的明码校验。
本文分享基于 Security 的 PasswordEncoder 来实现兼容多套用户明码加密形式。
二、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;
主动会依据数据的
encodingId
来应用对应的编译器解决明码
三、如何应用
3.1. 批改历史明码数据
批改旧的明码数据的值,增加前缀标识 encodingId
格局如下:
- 无盐值
{encodingId} 明码
例如源明码为:$2a$10$EgTOU7PMe.3jaMwFsumdweJcnY3TsTqyuJEdSaSKxdgwYchAwUJ1C
则批改为:{bcrypt}$2a$10$EgTOU7PMe.3jaMwFsumdweJcnY3TsTqyuJEdSaSKxdgwYchAwUJ1C
- 有盐值
{encodingId}{salt} 明码
例如源明码为:0758f7131c6c95c8e3df05e1ac50214c
则批改为:{MD5}{5Hstj}0758f7131c6c95c8e3df05e1ac50214c
encodingId 的值可参考
PwdEncoderUtil
类
如下图所示:
3 条记录中,前两条为原有的历史记录应用的是
MD5
的加密算法,而后新插入的数据应用的为bcrypt
的加密算法,别离应用不同的前缀标识encodingId
3.2. 配置 PasswordEncoder 对象
应用 DelegatingPasswordEncoder
类来定义 PasswordEncoder
并且指定默认加密形式为 bcrypt
@Bean
public PasswordEncoder passwordEncoder() {return PwdEncoderUtil.getDelegatingPasswordEncoder("bcrypt");
}
以下两种状况下都是应用默认的加密形式:
- 应用 encode 办法加密数据。
- 应用 matches 办法比照密文和原文时,密文没有 encodingId 标识。
3.3. 参考代码
https://gitee.com/zlt2000/microservices-platform/blob/master/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/PwdEncoderUtil.java
扫码关注有惊喜!