目录
一、为什么要对密码进行加盐加密?
1、明文
明文是一定不行的,因为会很容易就会泄露用户的个人隐私
2、传统的 MD5
传统的 MD5 是有规律可循的,虽然 MD5 是不可逆的,但是是可以被暴力破解的
因为一个 字符串的 MD5 的值是固定的,当你有了一张 MD5 的穷举表(彩虹表)之后,这张表中记录了几乎所有字符串的 MD5 对照表,就可以对密码进行暴力破解
二、加盐加密
所以我们选择使用加盐加密对密码进行处理,而这种处理方法中的盐值是随机不固定的,随机也就意味着没有规律可言
在进行了加盐加密之后,同样是一串明文密码,在不同时间对其进行调用,结果都是不同的,这也是因为每次调用,都有一个随机的盐值
1、加盐算法实现思路
每次调用方法的时候,产生盐值(唯一的),然后使用这个盐值再加上我们的密码,最终得到了一个密码
2、加盐算法解密思路
首先需要两个密码:
核心思想:得到盐值
我们将盐值存放到最终密码的某一个位置
从密码中 拿到盐值之后,我们才能对原始用户输入的密码按照相同的路径进行加密,然后和最终的密码进行对比,从而判断用户输入的密码是否正确
验证密码伪代码:
3、加盐算法代码实现
public class PasswordUtils {
/**
* 1、 加盐并生成密码
* @param password 明文密码
* @return 保存到数据库中的密码
*/
public static String encrypt(String password){
// 产生盐值(32位)
String salt = UUID.randomUUID().toString().replace("-","");
// 生成加盐之后的密码
String saltPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
// 生成最终的密码 (保存到数据库中的密码)【约定格式: 32位盐值 + $ + 32位加盐后密码】
String finalPassword = salt + "$" + saltPassword;
return finalPassword;
}
/**
* 2、生成加盐的密码(方法一的重载)
* @param password 明文
* @param salt 盐值
* @return 数据库中的最终密码
*/
public static String encrypt(String password,String salt) {
// 生成加盐之后的密码
String saltPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
// 生成最终的密码
String finalPassword = salt + "$" + saltPassword;
return finalPassword;
}
/**
* 3、验证密码
* @param inputPassword 用户输入的明文密码
* @param finalPassword 数据库中存储的最终密码
* @return
*/
public static boolean check(String inputPassword,String finalPassword){
if (!StringUtils.hasLength(inputPassword) || !StringUtils.hasLength(finalPassword)
|| finalPassword.length() != 65){
return false;
}
// 1、得到盐值
String salt = finalPassword.split("\\$")[0];
// 2、使用加密方式对明文和盐值进行加密
String confirmPassword = encrypt(inputPassword,salt);
// 进行对比
return confirmPassword.equals(finalPassword);
}
/* public static void main(String[] args) {
String password = "123456";
String finalPassword = PasswordUtils.encrypt(password);
System.out.println("加密:" + PasswordUtils.encrypt(password));
String inputPassword = "12345";
System.out.println("对比:" + inputPassword + "是否等于" + password + "结果" +
PasswordUtils.check(inputPassword,finalPassword));
String inputPassword2 = "123456";
System.out.println("对比:" + inputPassword2 + "是否等于" + password + "结果" +
PasswordUtils.check(inputPassword2,finalPassword));
}*/
}
三、使用 Spring Security 加盐
1、引入 Spring Security 框架
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2、排除 Spring Security 的自动加载
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
3、调用 Spring Security 的加盐
BCryPasswordEncoder passwordEncoder = new BCryPasswordEncoder();
String password = "123456";
String finalPassword = passwordEncoder.encode(password);
System.out.println("第一次加密:" + finalPassword);
System.out.println("第二次加密:" + passwordEncoder.encode(password));
System.out.println("第三次加密:" + passwordEncoder.encode(password));
// 验证
String inpuPassword = "12345";
System.out.println("错误密码比对结果:" + passwordEncoder.matches(inpuPassword,finalPassword));
String inputPassword2 = "123456";
System.out.println("错误密码比对结果:" + passwordEncoder.matches(inpuPassword2,finalPassword));