内容都在标题里面了 下面开始介绍环境
本文为技术实现文档 对为什么要使用和加密原理不做解析 后端为Springboot 前端为uni项目 vue2框架 js语言
我会在代码中说明每一行我踩的坑 并且附上通俗易懂的注释 详细阅读相信你一定会有收获
后端加密部分 传入一个object返回一个String密文
public String encrypt(Object data) throws Exception {
// 创建ObjectMapper实例,用于将数据转换为JSON字符串
ObjectMapper objectMapper = new ObjectMapper();
// 将数据转换为JSON字符串
// 注意这里可能直接拿去是无法直接跑起来的 可能会报错 说jdk8 无法格式化时间类
// 这个问题是因为你传入的对象中有LocalDateTime这个类型的属性
// 直接百度查询然后引入一个jackson-datatype-jsr310依赖就可以解决 对前后端
// 没有任何影响 具体的使用方法查询就好 也私信我 我单独写一篇
String jsonData = objectMapper.writeValueAsString(data);
// 生成一个安全随机的iv
// 这里调用自己写的 随机生成16位16进制的iv方法 代码在下面
String iv = getIv();
// 用于初始化向量参数
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
// 初始化加密算法
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// 初始化加密密钥和向量
// 注意这里的密钥是32字节的 因为使用了256位的方式 这样更加的安全 而且性能也不会很低
// 密钥长度可以是128位(16字节)、192位(24字节)或256位(32字节
SecretKeySpec secretKey = new SecretKeySpec("sZi8knPmD0BmXth3Ds48zSwBRs6Ow993".getBytes(), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
// 拿到加密后的数据
byte[] encryptedBytes = cipher.doFinal(jsonData.getBytes());
// 将IV和加密后的数据一起返回
// 将向量和密文进行base64编码 然后传递给前端
String encodedIV = Base64.getEncoder().encodeToString(iv.getBytes());
String encodedData = Base64.getEncoder().encodeToString(encryptedBytes);
return encodedIV + "|" + encodedData;
}
// 获取一个随机的16位16进制的iv向量
public String getIv(){
SecureRandom random = new SecureRandom();
byte[] bytes = new byte[8]; //8字节就是16个字符
random.nextBytes(bytes);
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
// 这里我目前通过测试 必须先拿到byte数组 然后格式化16进制 再去获取getbyte
// 然后再去base64编码 不然就会因为随机数出来的值中有负数
// 进行base64编码的时候 就是加密成功 前端也是解密不出来 而且base64的解码
// 也是完全不同 根本不可用
sb.append(String.format("%02x", b));
}
return sb.toString();
}
前端部分
decrypt(encryptedData) {
// 分离 IV 和加密数据
const parts = encryptedData.split('|');
const iv = CryptoJS.enc.Base64.parse(parts[0]); // 因为后端返回的时候把iv用base64编码了 所有需要用base64的格式化方法
const keyBytes = CryptoJS.enc.Utf8.parse('sZi8knPmD0BmXth3Ds48zSwBRs6Ow993'); //密钥是utf8格式的 所以需要使用utf8的格式方法
// 解密数据
const decryptedData = CryptoJS.AES.decrypt({
ciphertext: CryptoJS.enc.Base64.parse(parts[1]) //密文后端传递的也是base64的方法
},
keyBytes, {
iv: iv, //向量 必须经过CryptoJS.enc.Base64.parse转成对应的类型
mode: CryptoJS.mode.CBC,//模式
padding: CryptoJS.pad.Pkcs7//填充方式 位数不够补 等于号
}
);
// 将解密后的数据转换为明文
const decryptedText = decryptedData.toString(CryptoJS.enc.Utf8);
return JSON.parse(decryptedText) //转成对象返回
}