├── .gitignore
├── README.md
├── pom.xml
└── src
└── main
└── java
└── com
└── barcke
└── y
└── rsa
├── advice
├── DecryptHttpInputMessage.java
├── EncryptRequestBodyAdvice.java
└── EncryptResponseBodyAdvice.java
├── annotation
├── Decrypt.java
├── EnableSecurity.java
└── Encrypt.java
├── config
└── SecretKeyConfig.java
├── exception
└── EncryptRequestException.java
├── pojo
└── KeyInfo.java
└── util
├── Base64Util.java
├── JsonUtils.java
└── RSAUtil.java
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/test/**
5 |
6 | ### STS ###
7 | .apt_generated
8 | .classpath
9 | .factorypath
10 | .project
11 | .settings
12 | .springBeans
13 | .sts4-cache
14 |
15 | ### IntelliJ IDEA ###
16 | .idea
17 | *.iws
18 | *.iml
19 | *.ipr
20 | *.log
21 | *.lck
22 | /test/
23 |
24 | ### NetBeans ###
25 | /nbproject/private/
26 | /nbbuild/
27 | /dist/
28 | /nbdist/
29 | /.nb-gradle/
30 | build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # rsa-body-spring-boot
2 | ## 使用方式
3 | 导入对应的MAVEN包:
4 |
5 | ```
6 |
7 | com.barcke.y
8 | rsa-body-spring-boot
9 | 1.0.0
10 |
11 | ```
12 | 导入对应的包后开启配置项:
13 | ```
14 | rsa:
15 | encrypt:
16 | open: true # 是否开启加密 true or false
17 | showLog: true # 是否打印加解密log true or false 默认false
18 | timestampCheck: true #是否开启时间校验 默认false
19 | publicKey: #公钥信息
20 | privateKey: #私钥信息
21 | ```
22 | 可以使用如下方法生产公私钥:
23 | ```
24 | import com.barcke.y.rsa.util.RSAUtil
25 |
26 | //用于生产公私钥 返回值为对应的公私钥信息 生成后请保管好
27 | RSAUtil.genKeyPair();
28 | ```
29 |
30 | 开启配置项后在项目中使用注解:
31 | ```
32 | @Encrypt //加密
33 | @Decrypt(required = true, timeout = 30000L) //解密 required默认关闭,timeout超时时间设置
34 | ```
35 | 示例:
36 | 
37 | **注意传参方式为“application/json”加密会对整个回参加密,解密会对整个入参解密.**
38 |
39 | 前端加解密可以同步公私钥信息、不过需要注意RSA的长度加密为117解密为256超长是会报错的~
40 | 前端加解密可参考如下:
41 | ```
42 |
43 |
44 |
45 |
46 | 使用jsencrypt执行OpenSSL的RSA加密,解密
47 |
48 |
49 |
50 |
73 |
74 |
75 | ```
76 |
77 | ## 2021-03-05 升级如下
78 | ```
79 |
80 | com.barcke.y
81 | rsa-body-spring-boot
82 | 1.0.1
83 |
84 | ```
85 | #### 解决内容过长解密失败问题
86 |
87 | 支持版本JDK 1.8.0_251
88 | 过低不支持噢
89 | 1.8.0_251版本升级了RSA创建方式固过低不支持~
90 |
91 |
92 | # 主作人员
93 |
94 | imyzt
95 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.barcke.y
8 | rsa-body-spring-boot
9 | 1.0.1
10 | Springboot 参数自动加解密
11 |
12 | rsa-body-spring-boot
13 | jar
14 | https://github.com/Barcke/rsa-body-spring-boot
15 |
16 |
17 | UTF-8
18 | UTF-8
19 | 1.8
20 | 1.8
21 | 1.8
22 | true
23 | 2.1.4.RELEASE
24 | UTF-8
25 | ${java.home}/../bin/javadoc
26 |
27 |
28 |
29 |
30 | The Apache Software License, Version 2.0
31 | http://www.apache.org/licenses/LICENSE-2.0.txt
32 |
33 |
34 |
35 |
36 | https://github.com/Barcke/rsa-body-spring-boot
37 | scm:git:git@github.com:Barcke/rsa-body-spring-boot.git
38 | scm:git:git@github.com:Barcke/rsa-body-spring-boot.git
39 |
40 |
41 |
42 |
43 | barcke
44 | barcke
45 | barcke@163.com
46 |
47 | Developer
48 |
49 | +8
50 |
51 |
52 |
53 |
54 |
55 | release
56 |
57 | true
58 |
59 |
60 |
61 |
62 | org.apache.maven.plugins
63 | maven-source-plugin
64 | 2.2.1
65 |
66 |
67 | package
68 |
69 | jar-no-fork
70 |
71 |
72 |
73 |
74 |
75 | org.apache.maven.plugins
76 | maven-javadoc-plugin
77 | 2.9.1
78 |
79 |
80 | package
81 |
82 | jar
83 |
84 |
85 |
86 |
87 |
88 | org.apache.maven.plugins
89 | maven-gpg-plugin
90 | 1.6
91 |
92 |
93 | sign-artifacts
94 | verify
95 |
96 | sign
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | ossrh
106 | https://oss.sonatype.org/content/repositories/snapshots/
107 |
108 |
109 | ossrh
110 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | org.springframework.boot
120 | spring-boot-starter
121 | true
122 |
123 |
124 |
125 | org.springframework.boot
126 | spring-boot-starter-web
127 | true
128 |
129 |
130 |
131 | org.springframework.boot
132 | spring-boot-starter-test
133 | test
134 |
135 |
136 |
137 | commons-codec
138 | commons-codec
139 |
140 |
141 |
142 | org.apache.commons
143 | commons-lang3
144 | 3.8.1
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | org.springframework.boot
158 | spring-boot-dependencies
159 | ${springboot-version}
160 | pom
161 | import
162 |
163 |
164 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/src/main/java/com/barcke/y/rsa/advice/DecryptHttpInputMessage.java:
--------------------------------------------------------------------------------
1 | package com.barcke.y.rsa.advice;
2 |
3 | import com.barcke.y.rsa.annotation.Decrypt;
4 | import com.barcke.y.rsa.config.SecretKeyConfig;
5 | import com.barcke.y.rsa.exception.EncryptRequestException;
6 | import com.barcke.y.rsa.util.Base64Util;
7 | import com.barcke.y.rsa.util.JsonUtils;
8 | import com.barcke.y.rsa.util.RSAUtil;
9 | import org.apache.commons.lang3.StringUtils;
10 | import org.slf4j.Logger;
11 | import org.slf4j.LoggerFactory;
12 | import org.springframework.http.HttpHeaders;
13 | import org.springframework.http.HttpInputMessage;
14 | import sun.security.rsa.RSAPrivateCrtKeyImpl;
15 |
16 | import java.io.BufferedReader;
17 | import java.io.ByteArrayInputStream;
18 | import java.io.InputStream;
19 | import java.io.InputStreamReader;
20 | import java.security.interfaces.RSAPrivateKey;
21 | import java.util.Base64;
22 | import java.util.stream.Collectors;
23 |
24 | /**
25 | * ,;,,;
26 | * ,;;'( 社
27 | * __ ,;;' ' \ 会
28 | * /' '\'~~'~' \ /'\.) 主
29 | * ,;( ) / |. 义
30 | *,;' \ /-.,,( ) \ 码
31 | * ) / ) / )| 农
32 | * || || \)
33 | * (_\ (_\
34 | *
35 | * @author Barcke
36 | * @version 1.0
37 | **/
38 | public class DecryptHttpInputMessage implements HttpInputMessage {
39 |
40 | private Logger log = LoggerFactory.getLogger(this.getClass());
41 | private HttpHeaders headers;
42 | private InputStream body;
43 |
44 |
45 | public DecryptHttpInputMessage(HttpInputMessage inputMessage, SecretKeyConfig secretKeyConfig, Decrypt decrypt) throws Exception {
46 |
47 | String privateKey = secretKeyConfig.getPrivateKey();
48 | String charset = secretKeyConfig.getCharset();
49 | boolean showLog = secretKeyConfig.isShowLog();
50 | boolean timestampCheck = secretKeyConfig.isTimestampCheck();
51 |
52 | if (StringUtils.isEmpty(privateKey)) {
53 | throw new IllegalArgumentException("privateKey is null");
54 | }
55 |
56 | this.headers = inputMessage.getHeaders();
57 | String content = new BufferedReader(new InputStreamReader(inputMessage.getBody()))
58 | .lines().collect(Collectors.joining(System.lineSeparator()));
59 | String decryptBody;
60 | // 未加密内容
61 | if (content.startsWith("{")) {
62 | // 必须加密
63 | if (decrypt.required()) {
64 | log.error("not support unencrypted content:{}", content);
65 | throw new EncryptRequestException("not support unencrypted content");
66 | }
67 | log.info("Unencrypted without decryption:{}", content);
68 | decryptBody = content;
69 | } else {
70 | content = content.replaceAll(" ", "+");
71 | if (StringUtils.isEmpty(content)) {
72 | throw new EncryptRequestException("request body is empty");
73 | }
74 | RSAPrivateKey rsaPrivateKey = RSAPrivateCrtKeyImpl.newKey(Base64.getDecoder().decode(privateKey));
75 | decryptBody = new String(RSAUtil.decrypt(rsaPrivateKey, Base64Util.decode(content)), charset);
76 | if(showLog) {
77 | log.info("After decryption:{}, Encrypted data received:{}", decryptBody, content);
78 | }
79 | }
80 |
81 | // 开启时间戳检查
82 | if (timestampCheck) {
83 | // 容忍最小请求时间
84 | long toleranceTime = System.currentTimeMillis() - decrypt.timeout();
85 | long requestTime = JsonUtils.getNode(decryptBody, "timestamp").asLong();
86 | // 如果请求时间小于最小容忍请求时间, 判定为超时
87 | if (requestTime < toleranceTime) {
88 | log.error("Encryption request has timed out, toleranceTime:{}, requestTime:{}, After decryption:{}", toleranceTime, requestTime, decryptBody);
89 | throw new EncryptRequestException("request timeout");
90 | }
91 | }
92 |
93 | this.body = new ByteArrayInputStream(decryptBody.getBytes());
94 | }
95 |
96 | @Override
97 | public InputStream getBody(){
98 | return body;
99 | }
100 |
101 | @Override
102 | public HttpHeaders getHeaders() {
103 | return headers;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/com/barcke/y/rsa/advice/EncryptRequestBodyAdvice.java:
--------------------------------------------------------------------------------
1 | package com.barcke.y.rsa.advice;
2 |
3 | import com.barcke.y.rsa.annotation.Decrypt;
4 | import com.barcke.y.rsa.config.SecretKeyConfig;
5 | import com.barcke.y.rsa.exception.EncryptRequestException;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.core.MethodParameter;
10 | import org.springframework.http.HttpInputMessage;
11 | import org.springframework.http.converter.HttpMessageConverter;
12 | import org.springframework.web.bind.annotation.ControllerAdvice;
13 | import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
14 |
15 | import java.lang.reflect.Method;
16 | import java.lang.reflect.Type;
17 | import java.util.Objects;
18 |
19 | /**
20 | * ,;,,;
21 | * ,;;'( 社
22 | * __ ,;;' ' \ 会
23 | * /' '\'~~'~' \ /'\.) 主
24 | * ,;( ) / |. 义
25 | *,;' \ /-.,,( ) \ 码
26 | * ) / ) / )| 农
27 | * || || \)
28 | * (_\ (_\
29 | *
30 | * @author Barcke
31 | * @version 1.0
32 | **/
33 | @ControllerAdvice
34 | public class EncryptRequestBodyAdvice implements RequestBodyAdvice {
35 |
36 | private Logger log = LoggerFactory.getLogger(this.getClass());
37 |
38 | private boolean encrypt;
39 | private Decrypt decryptAnnotation;
40 |
41 | @Autowired
42 | private SecretKeyConfig secretKeyConfig;
43 |
44 | @Override
45 | public boolean supports(MethodParameter methodParameter, Type targetType, Class extends HttpMessageConverter>> converterType) {
46 | Method method = methodParameter.getMethod();
47 | if (Objects.isNull(method)) {
48 | encrypt = false;
49 | return false;
50 | }
51 | if (method.isAnnotationPresent(Decrypt.class) && secretKeyConfig.isOpen()) {
52 | encrypt = true;
53 | decryptAnnotation = methodParameter.getMethodAnnotation(Decrypt.class);
54 | return true;
55 | }
56 | // 此处如果按照原逻辑直接返回encrypt, 会造成一次修改为true之后, 后续请求都会变成true, 在不支持时, 需要做修正
57 | encrypt = false;
58 | return false;
59 | }
60 |
61 | @Override
62 | public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class extends HttpMessageConverter>> converterType) {
63 | return body;
64 | }
65 |
66 | @Override
67 | public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
68 | Class extends HttpMessageConverter>> converterType){
69 | if (encrypt) {
70 | try {
71 | return new DecryptHttpInputMessage(inputMessage, secretKeyConfig, decryptAnnotation);
72 | } catch (EncryptRequestException e) {
73 | throw e;
74 | } catch (Exception e) {
75 | log.error("Decryption failed", e);
76 | }
77 | }
78 | return inputMessage;
79 | }
80 |
81 | @Override
82 | public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
83 | Class extends HttpMessageConverter>> converterType) {
84 | return body;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/java/com/barcke/y/rsa/advice/EncryptResponseBodyAdvice.java:
--------------------------------------------------------------------------------
1 | package com.barcke.y.rsa.advice;
2 |
3 | import com.barcke.y.rsa.annotation.Encrypt;
4 | import com.barcke.y.rsa.config.SecretKeyConfig;
5 | import com.barcke.y.rsa.util.Base64Util;
6 | import com.barcke.y.rsa.util.JsonUtils;
7 | import com.barcke.y.rsa.util.RSAUtil;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.core.MethodParameter;
12 | import org.springframework.http.MediaType;
13 | import org.springframework.http.converter.HttpMessageConverter;
14 | import org.springframework.http.server.ServerHttpRequest;
15 | import org.springframework.http.server.ServerHttpResponse;
16 | import org.springframework.util.StringUtils;
17 | import org.springframework.web.bind.annotation.ControllerAdvice;
18 | import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
19 | import sun.security.rsa.RSAPublicKeyImpl;
20 |
21 | import java.lang.reflect.Method;
22 | import java.security.interfaces.RSAPublicKey;
23 | import java.util.Base64;
24 | import java.util.Objects;
25 |
26 | /**
27 | * ,;,,;
28 | * ,;;'( 社
29 | * __ ,;;' ' \ 会
30 | * /' '\'~~'~' \ /'\.) 主
31 | * ,;( ) / |. 义
32 | *,;' \ /-.,,( ) \ 码
33 | * ) / ) / )| 农
34 | * || || \)
35 | * (_\ (_\
36 | *
37 | * @author Barcke
38 | * @version 1.0
39 | **/
40 | @ControllerAdvice
41 | public class EncryptResponseBodyAdvice implements ResponseBodyAdvice