前后端 AES 加解密
1.场景
目前在公司有一个业务需求,会员邀请新会员注册时。前端生成邀请码后进行 AES 加密,后端解密后将邀请码存储到数据库中,是前端加密,后端解密的场景。在 CSDN、掘金等平台尝试了几个例子,又自己修改了下后达成了想要的效果。写这篇文章用以记录存档,欢迎大家讨论交流!
2.类库使用
3.后端代码实现
工具类:
这个 ENCODE_KEY 的长度有指定要求,所以我用 Hutool 的 MD5 加密工具将字符串加密了一层。
IV_KEY 偏移量是 16 位,同样有固定长度要求。
本文更新:实际场景中如果使用 get 方式传递密文,有可能出现 + 号特殊字符被转义的情况。于是更新了写法。
import cn.hutool.core.codec.Base64;
import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.symmetric.AES;
public class KeyUtil {
/**
* 密钥key
*/
private static final String ENCODE_KEY = DigestUtil.md5Hex("xx");
/**
* 偏移量。16 字节
*/
private static final String IV_KEY = "4382822409223508";
/**
* 将加密字符串进行解密
*
* @param data 加密字符串
* @return 解密后的结果
*/
public static String decryptFromString(String data) {
//先进行URL解码,避免特殊符号带来的问题
data = URLDecoder.decode(data, CharsetUtil.CHARSET_UTF_8);
AES aes = new AES(Mode.CBC, Padding.ISO10126Padding, Base64.decode(ENCODE_KEY), IV_KEY.getBytes());
return aes.decryptStr(Base64.decode(data));
}
/**
* 将字符串进行加密
*
* @param data 未加密的字符串
* @return 加密后的密文结果
*/
public static String encryptFromString(String data) {
AES aes = new AES(Mode.CBC, Padding.ISO10126Padding, Base64.decode(ENCODE_KEY), IV_KEY.getBytes());
//将Base64加密后的结果,进行URL编码,避免GET方式传输的问题
return URLEncodeUtil.encode(Base64.encodeUrlSafe(aes.encrypt(data)));
}
}
Junit 测试类:
@Test
public void testHutoolDecrypt() {
String encryptData = KeyUtil.encryptFromString("Hello World");
System.out.println("加密:" + encryptData);
String decryptData = KeyUtil.decryptFromString(encryptData);
System.out.println("解密:" + decryptData);
}
测试结果:
4.前端代码实现(只包含加密部分)
从上面的 GitHub 仓库地址下载了 js 代码后,将 js 本地引用,没有使用 npm 安装的方式使用(太麻烦....)
下方是例子:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body></body>
<script src="js/crypto-js.js"></script>
<script>
// 待加密的原文,使用 utf-8 编码处理
let message = CryptoJS.enc.Utf8.parse("加密原文");
// 密钥,我这里随意填写的,和后端的ENCODE_KEY对应即可
let key = CryptoJS.enc.Base64.parse("key");
// iv,和后端的IV_KEY对应即可
let iv = CryptoJS.enc.Utf8.parse("4382822409223508");
// 加密
let encrypted = CryptoJS.AES.encrypt(message, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Iso10126,
});
// 密文,使用 base64 编码后使用URL函数再转一遍,避免GET方式调用的问题
let cipherTextBase64 = encodeURIComponent(
CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
);
// 打印密文
console.log(cipherTextBase64);
</script>
</html>
前端加密后的结果在浏览器控制台上进行了打印,可以复制后直接调用 java 代码的解密 function 进行测试,我这里不再进行截图演示。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于