像一些隐私数据、肯定不能使用明文存储到数据库中。需要经过加密后进行保存,这篇文章记载使用MD5加密算法进行数据的加密存储。
文章目录
- 1、加入pom依赖
- 2、编写工具类
- 3、使用
-
- 3.1 注册时期加密
- 3.2 登录时期的校验密码
- 4、存储到数据库的信息
- 5、测试效果
1、加入pom依赖
<!--MD5依赖-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
2、编写工具类
package com.zyz.bookshopmanage.Utils;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
/**
* @author 静小文
* @version 1.0
* @data 2022/9/9 10:36
*/
public class MyMD5Util {
private static final String HEX_NUMS_STR = "0123456789ABCDEF";
private static final Integer SALT_LENGTH = 12;
//将16进制字符转换为字节数组
public static byte[] hexStringToByte(String hex) {
int len = (hex.length() / 2);
byte[] result = new byte[len];
char[] hexChars = hex.toCharArray();
for (int i = 0; i < len; i++) {
int pos = i * 2;
result[i] = (byte) (HEX_NUMS_STR.indexOf(hexChars[pos]) << 4 | HEX_NUMS_STR
.indexOf(hexChars[pos + 1]));
}
return result;
}
//将指定byte数组转换成16进制字符串
public static String byteToHexString(byte[] b) {
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
hexString.append(hex.toUpperCase());
}
return hexString.toString();
}
//验证口令是否合法
public static boolean validPassword(String password, String passwordInDb)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
// 将16进制字符串格式口令转换成字节数组
byte[] pwdInDb = hexStringToByte(passwordInDb);
// 声明盐变量
byte[] salt = new byte[SALT_LENGTH];
// 将盐从数据库中保存的口令字节数组中提取出来
System.arraycopy(pwdInDb, 0, salt, 0, SALT_LENGTH);
// 创建消息摘要对象
MessageDigest md = MessageDigest.getInstance("MD5");
// 将盐数据传入消息摘要对象
md.update(salt);
// 将口令的数据传给消息摘要对象
md.update(password.getBytes("UTF-8"));
// 生成输入口令的消息摘要
byte[] digest = md.digest();
// 声明一个保存数据库中口令消息摘要的变量
byte[] digestInDb = new byte[pwdInDb.length - SALT_LENGTH];
// 取得数据库中口令的消息摘要
System.arraycopy(pwdInDb, SALT_LENGTH, digestInDb, 0, digestInDb.length);
// 比较根据输入口令生成的消息摘要和数据库中消息摘要是否相同
if (Arrays.equals(digest, digestInDb)) {
// 口令正确返回口令匹配消息
return true;
} else {
// 口令不正确返回口令不匹配消息
return false;
}
}
//获得加密后的口令
public static String getEncryptedPwd(String password)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
// 声明加密后的口令数组变量
byte[] pwd = null;
// 随机数生成器
SecureRandom random = new SecureRandom();
// 声明盐数组变量
byte[] salt = new byte[SALT_LENGTH];
// 将随机数放入盐变量中
random.nextBytes(salt);
// 声明消息摘要对象
MessageDigest md = null;
// 创建消息摘要
md = MessageDigest.getInstance("MD5");
// 将盐数据传入消息摘要对象
md.update(salt);
// 将口令的数据传给消息摘要对象
md.update(password.getBytes("UTF-8"));
// 获得消息摘要的字节数组
byte[] digest = md.digest();
// 因为要在口令的字节数组中存放盐,所以加上盐的字节长度
pwd = new byte[digest.length + SALT_LENGTH];
// 将盐的字节拷贝到生成的加密口令字节数组的前12个字节,以便在验证口令时取出盐
System.arraycopy(salt, 0, pwd, 0, SALT_LENGTH);
// 将消息摘要拷贝到加密口令字节数组从第13个字节开始的字节
System.arraycopy(digest, 0, pwd, SALT_LENGTH, digest.length);
// 将字节数组格式加密后的口令转化为16进制字符串格式的口令
return byteToHexString(pwd);
}
}
3、使用
3.1 注册时期加密
核心部分:
//加密 encryptedPwd = MyMD5Util.getEncryptedPwd(user.getPassword());
/**
* 注册
*/
@RequestMapping(value = "/user/register", method = RequestMethod.POST)
public Result register(@RequestBody User user) {
String time = CurrentTime.getCurrentTime();
user.setRegisterTime(time);
String encryptedPwd = null;
int result = 0;
try {
//加密
encryptedPwd = MyMD5Util.getEncryptedPwd(user.getPassword());
user.setPassword(encryptedPwd);
//根据身份证和姓名判断是否已注册
Map<String, Object> map = new HashMap<>();
map.put("user_name", user.getUserName());
map.put("Id_Card", user.getIdCard());
List<User> baseUser = userMapper.selectByMap(map);
if (user == null) {
return Result.error().data("errMessage", "请输入用户的信息");
}
if (baseUser.size() > 0) {
return Result.error().data("errMessage", "该用户已经注册!");
}
result = userMapper.insert(user);
} catch (Exception e) {
e.printStackTrace();
}
if (result > 0) {
return Result.ok();
} else {
return Result.error();
}
}
3.2 登录时期的校验密码
核心部分:
MyMD5Util.validPassword(pwd, user.getPassword());
/**
* 登录
*
* @param name
* @param pwd
* @return
*/
@RequestMapping(value = "/user/login/{name}/{pwd}", method = RequestMethod.POST)
public Result login(@PathVariable("name") String name, @PathVariable("pwd") String pwd) {
User user = userMapper.findByName(name);
boolean flag = false;
if (user != null) {
try {
flag = MyMD5Util.validPassword(pwd, user.getPassword());
} catch (Exception e) {
e.printStackTrace();
}
} else {
return Result.error().data("errMessage", "不存在该用户");
}
if (flag) {
return Result.ok();
} else {
return Result.error().data("errMessage", "密码错误");
}
}