1.加密介绍
在MySQL数据库中, 我们常常需要对密码, ⾝份证号, ⼿机号等敏感信息进⾏加密, 以保证数据的安全性.
如果使⽤明⽂存储, 当⿊客⼊侵了数据库时, 就可以轻松获取到⽤⼾的相关信息, 从⽽对⽤⼾或者企业造成信息泄漏或者财产损失.
⽬前我们⽤⼾的密码还是明⽂设置的, 为了保护⽤⼾的密码信息, 我们需要对
密码进⾏加密
2.密码算法分类
1.
对称密码算法 是指加密秘钥和解密秘钥相同的密码算法. 常⻅的对称密码算法有: AES, DES, 3DES, RC4, RC5, RC6 等.
2.
⾮对称密码算法 是指加密秘钥和解密秘钥不同的密码算法. 该算法使⽤⼀个秘钥进⾏加密, ⽤另外⼀个秘钥进⾏解密.
◦
加密秘钥可以公开,⼜称为 公钥
◦
解密秘钥必须保密,⼜称为 私钥
常⻅的⾮对称密码算法有: RSA, DSA, ECDSA, ECC 等
3.
摘要算法 是指把任意⻓度的输⼊消息数据转化为固定⻓度的输出数据的⼀种密码算法. 摘要算法是不可逆的, 也就是⽆法解密. 通常⽤来检验数据的完整性的重要技术, 即对数据进⾏哈希计算然后⽐较摘要值, 判断是否⼀致. 常⻅的摘要算法有: MD5, SHA系列(SHA1, SHA2等), CRC(CRC8, CRC16, CRC32)
3.加密思路
博客系统中, 我们采⽤MD5算法来进⾏加密.
问题:
虽然经过MD5加密后的密⽂⽆法解密,
但由于相同的密码经过MD5哈希之后的密⽂是相同的,
当存储⽤⼾密码的数据库泄露后, 攻击者会很容易便能找到相同密码的⽤⼾,
从⽽降低了破解密码的难度.
因此, 在对⽤⼾密码进⾏加密时,需要考虑对密码进⾏包装,
即使是相同的密码, 也保存为不同的密⽂
.
即使⽤⼾输⼊的是弱密码, 也考虑进⾏增强, 从⽽增加密码被攻破的难度.
解决⽅案: 采⽤为
⼀个密码拼接⼀个随机字符来进⾏加密
, 这个随机字符我们称之为"盐". 假如有⼀个加盐后的加密串,⿊客通过⼀定⼿段这个加密串, 他拿到的明⽂并不是我们加密前的字符串, ⽽是加密前的字符串和盐组合的字符串, 这样相对来说⼜增加了字符串的安全性.
4.解密流程
MD5是不可逆的, 通常采⽤"判断哈希值是否⼀致"来判断密码是否正确.
如果⽤⼾输⼊的密码, 和盐值⼀起拼接后的字符串经过加密算法, 得到的密⽂相同, 我们就认为密码正确
(密⽂相同, 盐值相同, 推测明⽂相同)
5.写加密/解密⼯具类
public class SecurityUtil {
//1.对密码进行加密
public static String encrypt(String password) {
// 每次⽣成内容不同的,但⻓度固定 32 位的盐值
String salt = UUID.randomUUID().toString().replace("-", "");
// 最终密码=md5(盐值+原始密码)
String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
return salt + finalPassword;
}
//2.密码验证
//password 待验证密码
//finalPassword 最终正确的密码(数据库中加盐的密码)
public static boolean verify(String password,String finalPassword){
//⾮空校验
if (!StringUtils.hasLength(password) ||
!StringUtils.hasLength(finalPassword)){
return false;
}
//最终密码不是64位, 则不正确
if (finalPassword.length()!=64){
return false;
}
//盐值
String salt = finalPassword.substring(0,32);
// 使⽤盐值+待确认的密码⽣成⼀个最终密码
String securityPassword =
DigestUtils.md5DigestAsHex((salt + password).getBytes());
// 使⽤盐值+最终的密码和数据库的真实密码进⾏对⽐
return (salt + securityPassword).equals(finalPassword);
}
public static void main(String[] args) {
String finalPassword = encrypt("123456");
System.out.println(finalPassword);
System.out.println(verify("123456",finalPassword));
}
}
修改登录接⼝
User user = userService.getUserInfo(username);
if (user==null || !SecurityUtil.verify(password,user.getPassword())){
return -1;
}
mock一下
测试!!!
成功!!!