Loading

[spring security]使用BCryptPasswordEncoder对明文密码加密后匹配失败

参考: https://www.cnblogs.com/flydean/p/15292400.html

问题

项目中使用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

posted @ 2023-01-17 14:10  丘丘CRUD  阅读(798)  评论(0)    收藏  举报