在进行加盐算法的学习之前,我们要做的为什么要进行加盐加密?
对于密码的处理我们有两种传统的方法:
第一种是明文密码,但是显然这种方式虽然简便快捷,但是很容易泄露隐私,会造成很严重的安全问题。
第二种是传统的MD5加密,这种方法虽然是不可逆的,但是有可能被暴力破解,这种加密方式是有规律可循的,在下面代码中就演示了比如对于“123456”,那么对应的MD5加密后的密文就是e10adc3949ba59abbe56e057f20f883e,彩虹表就应运而生,在彩虹表里面,几乎记录了所有字符串的MD5对照表。
加盐加密算法中的盐就像做饭的厨师加盐一样,盐粒是随机的,没有规律可循,比如同样的“123456”密码,在第一次调用加盐算法和第二次调用加盐算法生成的结果都是不同的,因为每次调用都是生成随机的盐值。
加盐算法的实现:
一,自己实现
第一步:加密
先约定加密的形式,这里我使用的加密格式是盐值 + “$" + 用户明文密码。
盐值可以先使用UUID生成36位的字符串,然后将UIUID中的4个‘-’去掉后是32位
最终密码格式(65位):盐值(32位)+ $(分隔符) + 加密的密码(32位)
每次调用方法的时候产生唯一的盐值,然后将 (盐值 + “$" + 用户明文密码)进行MD5加密就可以得到 最终的密码,存储到数据库中。
//1.加盐生成密码
public static String encrypt(String password){
//盐值
String salt = UUID.randomUUID().toString().replace("-","");
//生成加盐之后的密码
String saltPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
//生成最终的密码(保存到数据库中)
String finalPassword = salt + "$" + saltPassword;
return finalPassword;
}
第二步:解密(核心思想:得到盐值)
在这一步需要两个密码:
1.需要验证的密码(用户输入的密码)
2.最终加密的密码(存在数据库中的密码)
先将第一个方法生成的盐值和用户输入的密码按照约定的密码格式进行加密,这一步加密主要是为了生成加密后的密码,然后和数据库中的密码做对比,判断用户输入的密码是否正确。
//2.生成加盐的密码(方法1的重载)
public static String encrypt(String password,String salt){
//生成加盐之后的密码
String saltPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
//生成最终的密码
String finalPassword = salt + "$" + saltPassword;
return finalPassword;
}
对比生成的最终密码和数据库中的最终密码是否相同
//3.验证密码
public static boolean check(String inputPassword,String finalPassword){
if(StringUtils.hasLength(inputPassword) && StringUtils.hasLength(finalPassword) &&
finalPassword.length() == 65){
//1.得到盐值
String salt = finalPassword.split("$")[0];
//2.将明文密码和得到的盐值进行加密生成加密的密码
String confirmPassword = PasswordUtils.encrypt(inputPassword,salt);
//3.对比
return confirmPassword.equals(finalPassword);
}
return false;
}
二,使用spring-boot自带的框架进行加盐和验证
1.首先需要在pom.xml中引入Spring Security框架
2.排除spring security的自动加载,需要在启动类上加上@SpringBootApplication(exclude = {SecurityAutoConfiguration.class}),因为spring-boot-security会自带一个登录页面,需要输入账号名为”user“和在idea控制台提示的特殊密码后才能进入我们自己的页面
3.调用security的加盐和验证
加盐代码如下:
验证代码如下: