问题
项目中使用Spring Security+JWT做认证授权
做修改密码逻辑时原逻辑如下
select oldPwd from user where id = 1;
if(oldPwd.equals(encoder.encode(newPwd))){ // always false
// 旧密码匹配正确 可以执行修改密码逻辑
}
分析
两次加密同一串密码后得到的密文是否相同?
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encode1 = passwordEncoder.encode("1234");
String encode2 = passwordEncoder.encode("1234");
System.out.println(encode1);
System.out.println(encode2);
输出:
$2a$10$JDJEy1MDjrSE4Dt3RZw/1OZtMiR0kX.Ya.5P6r5YfvdgyoCPB9vN2
$2a$10$mnmHsD/IjxJBpPm1ge3Fe.GCzz/8gj6j9te2uERJS4IV/ocwKl5Fe
可以看到, 得到的密文并不相同.
根本原因是使用BCryptPasswordEncoder加密时会使用随机盐对密码加密.
@Override
public String encode(CharSequence rawPassword) {
if (rawPassword == null) {
throw new IllegalArgumentException("rawPassword cannot be null");
}
String salt = getSalt();
return BCrypt.hashpw(rawPassword.toString(), salt);
}
private String getSalt() {
if (this.random != null) {
return BCrypt.gensalt(this.version.getVersion(), this.strength, this.random);
}
return BCrypt.gensalt(this.version.getVersion(), this.strength);
}
解决
应该使用BCryptPasswordEncoder#matches(CharSequence rawPassword, String encodedPassword)方法对新旧密码进行匹配
System.out.println(passwordEncoder.matches("1234", encode1));
System.out.println(passwordEncoder.matches("1234", encode2));
输出:
true
true