# springboot-security-example
**Repository Path**: nemo77/springboot-security-example
## Basic Information
- **Project Name**: springboot-security-example
- **Description**: 基于spingboot框架的接口报文加解密示例demo. Demo of api message encrypt/decrypt based on spring-boot.
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2022-03-04
- **Last Updated**: 2023-10-21
## Categories & Tags
**Categories**: Uncategorized
**Tags**: SpringBoot, RSA, AES, Security, Java
## README
# springboot-security-example
Demo of api message encrypt/decrypt based on spring-boot.
基于Spring-Boot框架的接口报文加解密示例demo.
## 加解密算法
AES+RSA
AES是常用的对称加密算法,RSA是常用的非对称加密算法.
由于两种加密方式各有优劣,一般实际应用时扬长避短,使用对称加密法加密报文,使用非对称加密法加密对称加密的密钥.
### 加解密流程
#### 客户端到服务端
1. 服务端生成RSA公钥(publicKey)、私钥(privateKey).
2. 客户端生成AES密钥(aesKey),使用AES将报文加密成密文(data).
3. 客户端获取publicKey,使用RSA对aesKey加密(encryptKey).
4. 客户端将data和encryptKey作为参数传给服务端.
#### 服务端返回结果给客户端
因为从客户端传来的aesKey是安全的,所以服务端直接用aesKey加密返回报文,将密文返回即可.
## 在Spring Boot项目中实现加解密的流程
1. 通过过滤器*SecurityFilter*定义接口过滤规则,对需要接解密的接口拦截并进行下一步操作
2. 将过滤器拦截到的接口的请求报文,使用*RequestHandler*进行解密操作,并将解密后的明文通过过滤器的doFilter进一步发送到Controller的接口中
3. 接口收到请求报文,对数据进行处理后,将返回数据返回出去
4. 通过*ResponseResultHandler*对返回报文加密,*ResponseResultHandler*使用@ControllerAdvice注解,指定需要对返回结果进行加密处理的接口所在的包
## 项目结构
* **api** 服务接口定义层(interface).只定义接口,不实现具体业务.
* **provider** 服务接口实现层.实现接口所要实现的业务逻辑,包含与sql、NoSql、消息队列等外部系统的交互.
* **consumer** 服务消费层.接收HTTP请求获取请求报文(Controller),调用api层定义的服务接口得到处理结果,并包装成返回报文返回出去.
## 实现原理
通过过滤器filter拦截接口,解密报文;对返回报文加密处理。
步骤如下:
1. consumer中的filter.[SecurityFilter](springboot-security-example-consumer/src/main/java/com/nemo/consumer/filter/SecurityFilter.java "拦截器")拦截需要解密的接口,将请求报文交给handler.[RequestHandler](springboot-security-example-consumer/src/main/java/com/nemo/consumer/handler/RequestHandler.java)处理。其中,请求报文的格式如下:
- bizContent: AES加密后的接口入参密文
- domain: RSA加密后的AES密钥
- appId: appId用于区分请求来源
2. [RequestHandler](springboot-security-example-consumer/src/main/java/com/nemo/consumer/handler/RequestHandler.java "请求报文处理")解析请求报文中的数据。
通过appId调用[SecurityService](springboot-security-example-api/src/main/java/com/nemo/api/service/SecurityService.java "加解密密钥相关服务")服务从redis中获取到RSA私钥privateKey。
使用privateKey对domain进行RSA解密,得到AES密钥domainKey。
使用domainKey对bizContent进行AES解密得到明文data。
将data和domainKey重新放回HttpRequest.body,发送给Controller接口
3. Controller层接口接收到data后进行业务处理得到返回数据,将返回数据和domainKey一起返回出去
4. [ResponseResultHandler](springboot-security-example-consumer/src/main/java/com/nemo/consumer/handler/ResponseResultHandler.java "处理返回数据")拦截到返回数据,使用domainKey对data进行加密,再将加密后的响应报文返回给接口调用方
至此,接口数据的加解密完成。
## 接口调用Demo
位于consumer的[CipherTest.java](springboot-security-example-consumer/src/test/java/com/nemo/consumer/CipherTest.java "API加解密完整调用demo")展示了一次完整的接口调用,包括:
1. 原始请求报文AES加密;
2. 对AES密钥加密;
3. 构造加密请求报文;
4. 调用接口获取返回报文;
5. 对返回报文进行AES解密
等主要步骤。