目录
一、问题
二、密码加密
1、MD5密码加密
2、BCryptPasswordEncoder加密(推荐)
2.1 特点
2.2 使用步骤
一、问题
在数据库表中的密码都是明文存储的,安全性太低
需求:
将密码加密后存储,提高安全性
二、密码加密
1、MD5密码加密
MD5讯息摘要演算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码杂凑函数,可以产生出一个128位元(16位元组)的散列值(hash value),用于确保信息传输完整一致。
功能:
输入任意长度的信息,经过处理,输出为128位的信息
不同的输入得到的不同的结果,结果与输入都是一一对应的
可以使用Spring提供给我们的工具类DigestUtils的md5DigestAsHex方法
//密码比对(使用MD5加密)
//对前端传过来的明文密码进行MD5加密处理
password = DigestUtils.md5DigestAsHex(password.getBytes());
if (!password.equals(employee.getPassword())) {
//密码错误
throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
}
2011年后MD5加密算法可以被反推出来明文,被破解,已经不推荐使用
2、BCryptPasswordEncoder加密(推荐)
BCrypt 是一种密码散列函数,即单向函数。且每次加密过后的值都不一样!
2.1 特点
加密
注册用户时,使用SHA-256+随机盐+密钥把用户输入的密码进行hash处理,得到密码的hash值,然后将其存入数据库中。
密码匹配
用户登录时,密码匹配阶段并没有进行密码解密(因为密码经过Hash处理,是不可逆的),而是使用相同的算法把用户输入的密码进行hash处理,得到密码的hash值,然后将其与从数据库中查询到的密码hash值进行比较。如果两者相同,说明用户输入的密码正确
2.2 使用步骤
导入依赖(仓库地址Maven Repository: org.springframework.security » spring-security-crypto (mvnrepository.com))
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>6.2.1</version>
</dependency>
添加加密器
在 SpringBoot 项目的配置文件中添加如下代码,用于注入 BCryptPasswordEncoder 加密器
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
public class PasswordEncoderConfiguration {
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
验证密码
在需要验证密码的地方,通过@Autowired注解注入密码加密器,然后使用 BCryptPasswordEncoder 的 matches 方法进行匹配
@Autowired
private BCryptPasswordEncoder passwordEncoder;
// 使用BCryptPasswordEncoder
// 密码比对
if (!passwordEncoder.matches(password,employee.getPassword())) {
//密码错误
throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
}
加密方法:用于更改密码时将用户输入的明文密码进行加密
encode(明文密码)
匹配方法:用于比较输入的密码加密后与数据库中已加密的密码进行比对
matches(用户输入的未加密的密码,数据库中已加密的密码)
源码:
public String encode(CharSequence rawPassword) {
if (rawPassword == null) {
throw new IllegalArgumentException("rawPassword cannot be null");
} else {
String salt = this.getSalt();
return BCrypt.hashpw(rawPassword.toString(), salt);
}
}
public boolean matches(CharSequence rawPassword, String encodedPassword) {
if (rawPassword == null) {
throw new IllegalArgumentException("rawPassword cannot be null");
} else if (encodedPassword != null && encodedPassword.length() != 0) {
if (!this.BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
this.logger.warn("Encoded password does not look like BCrypt");
return false;
} else {
return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
}
} else {
this.logger.warn("Empty encoded password");
return false;
}
}