Spring Security 提供了BCryptPasswordEncoder类,实现Spring的PasswordEncoder接口使用BCrypt强哈希方法来加密密码。
BCrypt强哈希方法 每次加密的结果都不一样。
示例:
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class Test {
public static void main(String[] args){
String password = "wch_test_123456";
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(6);
String hashedPassword1 = passwordEncoder.encode(password);
String hashedPassword2 = passwordEncoder.encode(password);
String hashedPassword3 = passwordEncoder.encode(password);
String hashedPassword4 = passwordEncoder.encode(password);
System.out.println(hashedPassword1);
System.out.println(hashedPassword2);
System.out.println(hashedPassword3);
System.out.println(hashedPassword4);
boolean match1 = passwordEncoder.matches(password, hashedPassword1);
System.out.println(match1);
boolean match2 = passwordEncoder.matches(password, hashedPassword2);
System.out.println(match2);
boolean match3 = passwordEncoder.matches(password, hashedPassword3);
System.out.println(match3);
boolean match4 = passwordEncoder.matches(password, hashedPassword4);
System.out.println(match4);
}
}
BCryptPasswordEncoder方法对密码进行加密(encode)与密码匹配(matches)
spring security中的BCryptPasswordEncoder方法采用SHA-256 +随机盐+密钥对密码进行加密。SHA系列是Hash算法,不是加密算法,使用加密算法意味着可以解密(这个与编码/解码一样),但是采用Hash处理,其过程是不可逆的。
(1)加密(encode):注册用户时,使用SHA-256+随机盐+密钥把用户输入的密码进行hash处理,得到密码的hash值,然后将其存入数据库中。
(2)密码匹配(matches):用户登录时,密码匹配阶段并没有进行密码解密(因为密码经过Hash处理,是不可逆的),而是使用相同的算法把用户输入的密码进行hash处理,得到密码的hash值,然后将其与从数据库中查询到的密码hash值进行比较。如果两者相同,说明用户输入的密码正确。
这正是为什么处理密码时要用hash算法,而不用加密算法。因为这样处理即使数据库泄漏,黑客也很难破解密码
思考:既然这种加密方式是不可逆的,那么当用户忘记密码后呢?后台管理也查看不到密码。
实际上,现在有部分是通过某种加密方式,用加密包对密码进行加密,存储到数据库中,可以使用相应的解密包能获取到用户的原始密码。但现在为了用户的信息安全,实际上是做到连后台管理员都无法直接看到用户的密码信息。现在大多数系统都是绑定手机或者邮箱之类的,当用户忘记密码后都是通过手机验证码或者邮箱的形式让用户重置密码,并不能够直接找系统管理员获取到密码。