目录
原理
使用AES加密算法
加密算法有很多,大多使用AES算法,该算法是一种对称算法(即前后端用的key是相同的)
Java 中的 javax.crypto.Cipher 类提供加密和解密方法。
使用AOP
参考链接:
使用Spring AOP修改请求、返回参数 - niithub的个人空间 - OSCHINA - 中文开源技术交流社区
过滤器,拦截器,AOP的关系:
(3条消息) Spring 过滤器 拦截器 AOP区别_笃行淡言-CSDN博客_aop和拦截器的区别
AES加密实战
参考:
https://segmentfault.com/a/1190000039373626
步骤
1. 引入 web 依赖,再引入加密解密用的 starter 依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.github.lenve</groupId>
<artifactId>encrypt-spring-boot-starter</artifactId>
<version>0.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
2. 测试
@RestController
public class HelloController {
@GetMapping("/user")
@Encrypt
public RespBean getUser() {
User user = new User();
user.setId((long) 99);
user.setUsername("javaboy");
return RespBean.ok("ok", user);
}
@PostMapping("/user")
public RespBean addUser(@RequestBody @Decrypt User user) {
System.out.println("user = " + user);
return RespBean.ok("ok", user);
}
}
第一个接口使用了 @Encrypt 注解,所以会对该接口的返回数据进行加密(如果不使用该注解就不加密)
第二个接口使用了 @Decrypt 所以会对上传的参数进行解密,注意 @Decrypt 注解既可以放在方法上也可以放在参数上。如果前端传来的是加密后的数据,就必须先进行解密。
User为定义好的用户类,RespBean定义好的统一响应类
存在问题
1. 如果传来的是多个参数,在实际应用中使用了自定义注解@MultiRequestBody,无法进行先拆分RequestBody,再进行解密
链接:SpringBoot Controller 中使用多个@RequestBody的正确姿势_明明如月的技术博客-CSDN博客_requestbody注解多个参数
2. 使用对称的key,在前端打开开发者工具 ,从js文件中可以直接找到key,存在安全问题
想法
针对问题1. :
1. 如果不使用MuitiRequestBody注解,接收整个Object进行解密(当然加密的时候也需要整体的加密),然后再进行拆分各个参数
2. 如果使用@MultiRequestBody,尝试将参数分别加密如下图所示:
在MultiRequestBody类方法中分别进行解密,但存在问题:如果并不是每个接口都需要解密,但每个接口都会用到@MultiRequestBody
3. 使用AOP进行对参数的加密和解密
参考链接:
使用Spring AOP修改请求、返回参数 - niithub的个人空间 - OSCHINA - 中文开源技术交流社区
针对问题2:
1. 如果用非对称的key,只能看到前端的key,后端用另外一个key,是否就安全
2. 是否有方法实现动态生成的key?
3. 是否可以对post请求的参数名进行加密?(即前端开发者模式显示的接口参数名)