# 一、背景与问题
有时候我们需要对一些关键接口进行数据加密,返回给前端,前端解密后,后端进行解密;
# 二、架构与思想
接口的加解密很容易想到 AOP,那么AOP又离不开 注解,所以我们定义了一个切面和两个注解(加解密各一个);
接口加密的模块叫做: jwe (JSON Web Encrypt)
# 三、具体使用
# 3.1、配置密钥key
密钥是JweUserKey
,与用户相关的,这这样能保证每个用户的加密数据都不一样;
在使用的项目中配置config
类,比如在sa-admin
的config
包下面JweAspectConfig.java
,具体配置如下:
@Configuration
public class JweAspectConfig {
/**
* 配置信息
*/
@Bean
public JweAspect jweConfig() {
return new JweAspect((request -> {
RequestUser requestUser = SmartRequestUtil.getRequestUser();
JweUserKey userKey = new JweUserKey();
userKey.setUserId(requestUser.getUserId());
userKey.setUserName(requestUser.getUserName());
userKey.setExtData(requestUser.getUserType().getValue().toString());
return userKey;
}));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 3.2、加密@JweEncrypt
在需要加密的 controller方法上加上注解 @JweEncrypt
# 3.3、解密@JweDecrypt
在需要解密的 controller方法上加上注解 @JweDecrypt
# 四、实现原理
一共分两步:
- 第一步: base64 转换
- 第二步: 加密 或者 解密
# 4.1、AOP切面 解密
JweAspect.java
@Before("@annotation(net.lab1024.sa.common.module.support.jwe.JweDecrypt)")
public void before(JoinPoint joinPoint) {
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
JweDecrypt annotation = method.getAnnotation(JweDecrypt.class);
if (annotation == null) {
return;
}
Object[] params = joinPoint.getArgs();
if (params == null) {
return;
}
if (params.length == 0) {
return;
}
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
JweUserKey user = this.userFunction.apply(request);
if (user == null) {
return;
}
Boolean decryptParamFlag = params[0] instanceof DecryptData;
if (!decryptParamFlag) {
return;
}
DecryptData decryptData = (DecryptData) params[0];
String data = decryptData.getData();
log.info("解密前数据:{}", data);
String key = SecureUtil.md5(String.format(MD5_SALT_FORMAT, user.getUserId()));
log.info("解密KEY数据:{}", key);
//初始化向量是16位长度
String iv = key.substring(0, 16);
//解密
AES aes = new AES(Mode.CTS, Padding.PKCS5Padding, key.getBytes(), iv.getBytes());
data = aes.decryptStr(data);
log.info("解密后数据:{}", data);
//base64解码
data = new String(Base64Utils.decodeFromString(data));
log.info("base64解码后数据:{}", data);
decryptData.setData(data);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 4.2、AOP切面 加密
JweAspect.java
@AfterReturning(returning = "object", pointcut = "@annotation(net.lab1024.sa.common.module.support.jwe.JweEncrypt)")
public void afterReturning(JoinPoint joinPoint, Object object) {
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
JweEncrypt annotation = method.getAnnotation(JweEncrypt.class);
if (annotation == null) {
return;
}
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
JweUserKey user = this.userFunction.apply(request);
if (user == null) {
return;
}
try {
ResponseDTO responseDTO = (ResponseDTO) object;
Object data = responseDTO.getData();
if (data == null) {
return;
}
String jsonData = JSON.toJSONString(data, SerializerFeature.DisableCircularReferenceDetect);
log.info("JSON 原数据:{}", jsonData);
//base64编码
jsonData = Base64Utils.encodeToString(jsonData.getBytes("utf-8"));
log.info("JSON Base64数据:{}", jsonData);
//加密秘钥
String key = SecureUtil.md5(String.format(MD5_SALT_FORMAT, user.getUserId()));
log.info("JSON MD5 KEY数据:{}", key);
//初始化向量是16位长度
String iv = key.substring(0, 16);
//AES 加密
AES aes = new AES(Mode.CTS, Padding.PKCS5Padding, key.getBytes(), iv.getBytes());
data = aes.encryptBase64(jsonData);
log.info("JSON ASE 加密数据:{}", jsonData);
responseDTO.setData(jsonData);
} catch (Exception e) {
log.error(e.getMessage(),e);
return;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 联系我们
1024创新实验室-主任:卓大 (opens new window),混迹于各个技术圈,研究过计算机,熟悉点 java,略懂点前端。
1024创新实验室(河南·洛阳) (opens new window) 致力于成为中原领先、国内一流的技术团队,以技术创新为驱动,合作各类项目(软件外包、技术顾问、培训等等)。
![]() | ![]() | ![]() |
加 主任 “卓大” 微信 拉你入群,一起学习 | 关注 “小镇程序员” 分享代码与生活、技术与赚钱 | 请 “1024创新实验室” 喝咖啡 支持我们的开源与分享 |