登录密码对于用户来说是最重要的数据,所以在存储的时候需要进行加密,防止在一些外部攻击下用户重要数据被别人获取了。对于登录密码加密,本人整理了三种简单的方式。
具体思路如下:
一、数据库加密
1、在后端存入数据库时,通过sql语句进行对应数据库的数据加密方式,具体sql语句如下:
(1)敏感数据参数#{data}改为AES_ENCRYPT(#{data},'MySQL')
//在dao层写一条插入语句,插入用户名和密码,密码加密
@Insert("insert into user values(#{username},AES_ENCRYPT(#{password},'MySQL'))")
public int addUser(String username,String password);
2、在建表时,对应密码字段的类型改为用varbinary类型存储,具体sql语句如下:
create database lib;
use lib;
create table user(
username varchar(11),
password varbinary(255)
);
3、这里省略service层,在controller层添加插入方法,用apifox测试接口,插入成功
//当插入成功就返回true
@PostMapping("/user")
public boolean addUser(String username,String password){
return userDao.addUser(username,password);
}
3、前往数据库查看数据库中的数据是否加密,可以看到密码加密成功
4、但这种加密方式是可以解密的,可以通过sql语句如下解密,所以不太建议使用。
@Select("select username,AES_DECRYPT(password,'MySQL') AS password from user where username=#{username} and password = #{password}")
public User searchUser(@Param("username") String username,@Param("password") String password);
二、后端创建工具类MD5加密
1、新建工具类
public class HashEncryption {
public String encrypt(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(password.getBytes("UTF-8"));
byte[] results = md.digest();
StringBuilder sb = new StringBuilder();
for (byte bite : results) {
sb.append(String.format("%02x", bite));
}
return sb.toString();
}
}
2、controller层new 工具类,传递密码参数返回加密后的密码,插入成功同样返回true
@PostMapping("/user")
public boolean addUser(String username,String password) throws UnsupportedEncodingException, NoSuchAlgorithmException {
HashEncryption hashEncryption=new HashEncryption();
return userService.addUser(username,hashEncryption.encrypt(username));
}
3、apifox测试方式同上,控制台debug结果如下,插入的密码为加密后的b0baee9d279d34fa1dfd71aadb908c3f
4、这种方式不会被解密,但是可能会让别人通过拦截前端传递的数据,得到前端未加密的数据。
三、前端加密
1、通过前端加密后传递给后端加密后的密码
可以参考:前端利用md5进行加密_js-md5 -d_~天吻蓝了海的博客-CSDN博客
四、总结
1、数据库加密,可能会被解密
2、后端工具类加密,可能会被别人拦截前端传递的数据,导致泄露。
3、前端加密是一个优解,在不影响执行速度情况下。当然想前后端都加密一次也可以。