Skip to content

Commit 49fafc8

Browse files
committed
feat: 增加声明类及指定字段的支持 #15
1 parent b5150ec commit 49fafc8

15 files changed

+272
-188
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ buildNumber.properties
1212
!/.mvn/wrapper/maven-wrapper.jar
1313
.idea/*
1414
*.iml
15+
src/main/java/cn/licoy/encryptbody/test

src/main/java/cn/licoy/encryptbody/advice/DecryptRequestBodyAdvice.java

Lines changed: 90 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
package cn.licoy.encryptbody.advice;
22

33
import cn.hutool.core.io.IoUtil;
4+
import cn.hutool.core.util.ReflectUtil;
45
import cn.hutool.core.util.StrUtil;
56
import cn.hutool.crypto.SecureUtil;
67
import cn.hutool.crypto.asymmetric.RSA;
8+
import cn.licoy.encryptbody.annotation.FieldBody;
79
import cn.licoy.encryptbody.annotation.decrypt.AESDecryptBody;
810
import cn.licoy.encryptbody.annotation.decrypt.DESDecryptBody;
911
import cn.licoy.encryptbody.annotation.decrypt.DecryptBody;
1012
import cn.licoy.encryptbody.annotation.decrypt.RSADecryptBody;
11-
import cn.licoy.encryptbody.annotation.encrypt.RSAEncryptBody;
1213
import cn.licoy.encryptbody.bean.DecryptAnnotationInfoBean;
1314
import cn.licoy.encryptbody.bean.DecryptHttpInputMessage;
1415
import cn.licoy.encryptbody.config.EncryptBodyConfig;
1516
import cn.licoy.encryptbody.enums.DecryptBodyMethod;
1617
import cn.licoy.encryptbody.exception.DecryptBodyFailException;
1718
import cn.licoy.encryptbody.exception.DecryptMethodNotFoundException;
1819
import cn.licoy.encryptbody.util.CommonUtils;
20+
import com.fasterxml.jackson.databind.ObjectMapper;
1921
import lombok.extern.slf4j.Slf4j;
2022
import org.springframework.core.MethodParameter;
2123
import org.springframework.core.annotation.Order;
@@ -24,7 +26,8 @@
2426
import org.springframework.web.bind.annotation.ControllerAdvice;
2527
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
2628

27-
import java.lang.annotation.Annotation;
29+
import java.lang.reflect.AnnotatedElement;
30+
import java.lang.reflect.Field;
2831
import java.lang.reflect.Method;
2932
import java.lang.reflect.Type;
3033

@@ -44,25 +47,35 @@ public class DecryptRequestBodyAdvice implements RequestBodyAdvice {
4447

4548
private final EncryptBodyConfig config;
4649

47-
public DecryptRequestBodyAdvice(EncryptBodyConfig config) {
50+
private final ObjectMapper objectMapper;
51+
52+
public DecryptRequestBodyAdvice(ObjectMapper objectMapper, EncryptBodyConfig config) {
53+
this.objectMapper = objectMapper;
4854
this.config = config;
4955
}
5056

5157
@Override
5258
public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
53-
Annotation[] annotations = methodParameter.getDeclaringClass().getAnnotations();
54-
if (annotations.length > 0) {
55-
for (Annotation annotation : annotations) {
56-
if (annotation instanceof DecryptBody || annotation instanceof AESDecryptBody || annotation instanceof DESDecryptBody || annotation instanceof RSADecryptBody) {
59+
if (this.hasDecryptAnnotation(methodParameter.getDeclaringClass())) {
60+
return true;
61+
}
62+
Method method = methodParameter.getMethod();
63+
if (method != null) {
64+
if (this.hasDecryptAnnotation(method)) {
65+
return true;
66+
}
67+
Class<?>[] parameterTypes = method.getParameterTypes();
68+
for (Class<?> parameterType : parameterTypes) {
69+
if (this.hasDecryptAnnotation(parameterType)) {
5770
return true;
5871
}
5972
}
6073
}
61-
Method method = methodParameter.getMethod();
62-
if (method == null) {
63-
return false;
64-
}
65-
return method.isAnnotationPresent(DecryptBody.class) || method.isAnnotationPresent(AESDecryptBody.class) || method.isAnnotationPresent(DESDecryptBody.class) || method.isAnnotationPresent(RSADecryptBody.class);
74+
return false;
75+
}
76+
77+
private boolean hasDecryptAnnotation(AnnotatedElement annotatedElement) {
78+
return annotatedElement.isAnnotationPresent(DecryptBody.class) || annotatedElement.isAnnotationPresent(AESDecryptBody.class) || annotatedElement.isAnnotationPresent(DESDecryptBody.class) || annotatedElement.isAnnotationPresent(RSADecryptBody.class);
6679
}
6780

6881
@Override
@@ -81,12 +94,33 @@ public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodPara
8194
if (body == null || StrUtil.isEmpty(body)) {
8295
throw new DecryptBodyFailException("The request body is NULL or an empty string, so the decryption failed." + " (请求正文为NULL或为空字符串,因此解密失败。)");
8396
}
97+
Class<?> targetTypeClass;
98+
try {
99+
targetTypeClass = Class.forName(targetType.getTypeName());
100+
} catch (ClassNotFoundException e) {
101+
throw new DecryptBodyFailException(e.getMessage());
102+
}
84103
String decryptBody = null;
85-
DecryptAnnotationInfoBean methodAnnotation = this.getMethodAnnotation(parameter);
104+
DecryptAnnotationInfoBean methodAnnotation = this.getDecryptAnnotation(parameter.getMethod());
86105
if (methodAnnotation != null) {
87106
decryptBody = switchDecrypt(body, methodAnnotation);
107+
} else if (this.hasDecryptAnnotation(targetTypeClass)) {
108+
if (targetTypeClass.isAnnotationPresent(FieldBody.class)) {
109+
try {
110+
Object bodyInstance = objectMapper.readValue(body, targetTypeClass);
111+
Object decryptBodyInstance = this.eachClassField(bodyInstance, targetTypeClass);
112+
decryptBody = objectMapper.writeValueAsString(decryptBodyInstance);
113+
} catch (Exception e) {
114+
throw new DecryptBodyFailException(e.getMessage());
115+
}
116+
} else {
117+
DecryptAnnotationInfoBean classAnnotation = this.getDecryptAnnotation(targetTypeClass);
118+
if (classAnnotation != null) {
119+
decryptBody = switchDecrypt(body, classAnnotation);
120+
}
121+
}
88122
} else {
89-
DecryptAnnotationInfoBean classAnnotation = this.getClassAnnotation(parameter.getDeclaringClass());
123+
DecryptAnnotationInfoBean classAnnotation = this.getDecryptAnnotation(parameter.getDeclaringClass());
90124
if (classAnnotation != null) {
91125
decryptBody = switchDecrypt(body, classAnnotation);
92126
}
@@ -106,69 +140,72 @@ public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodPa
106140
return body;
107141
}
108142

143+
private Object eachClassField(Object body, Class<?> clazz) {
144+
Field[] declaredFields = clazz.getDeclaredFields();
145+
for (Field field : declaredFields) {
146+
field.setAccessible(true);
147+
DecryptAnnotationInfoBean decryptAnnotation = this.getDecryptAnnotation(field);
148+
Class<?> type = field.getType();
149+
if (decryptAnnotation != null) {
150+
FieldBody fieldBody = field.getAnnotation(FieldBody.class);
151+
if (fieldBody != null) {
152+
Field setField = ReflectUtil.getField(clazz, fieldBody.field());
153+
if (setField != null && setField.getType().equals(String.class)) {
154+
Object fieldValue = ReflectUtil.getFieldValue(body, setField);
155+
String decryptResult = this.switchDecrypt(String.valueOf(fieldValue), decryptAnnotation);
156+
ReflectUtil.setFieldValue(body, field, decryptResult);
157+
}
158+
} else if (type.equals(String.class)) {
159+
String decryptResult = this.switchDecrypt(String.valueOf(ReflectUtil.getFieldValue(body, field)), decryptAnnotation);
160+
ReflectUtil.setFieldValue(body, field, decryptResult);
161+
}
162+
} else if (!CommonUtils.isConvertToString(type)) {
163+
Object fieldValue = ReflectUtil.getFieldValue(body, field);
164+
if (fieldValue != null) {
165+
this.eachClassField(fieldValue, type);
166+
}
167+
}
168+
}
169+
return body;
170+
}
171+
109172
/**
110-
* 获取方法控制器上的加密注解信息
173+
* 获取解密注解的数据
111174
*
112-
* @param methodParameter 控制器方法
113-
* @return 加密注解信息
175+
* @param annotatedElement 注解元素
176+
* @return 解密注解组装数据
114177
*/
115-
private DecryptAnnotationInfoBean getMethodAnnotation(MethodParameter methodParameter) {
116-
Method method = methodParameter.getMethod();
117-
if (method == null) {
178+
private DecryptAnnotationInfoBean getDecryptAnnotation(AnnotatedElement annotatedElement) {
179+
if (annotatedElement == null) {
118180
return null;
119181
}
120-
if (method.isAnnotationPresent(DecryptBody.class)) {
121-
DecryptBody decryptBody = methodParameter.getMethodAnnotation(DecryptBody.class);
182+
if (annotatedElement.isAnnotationPresent(DecryptBody.class)) {
183+
DecryptBody decryptBody = annotatedElement.getAnnotation(DecryptBody.class);
122184
if (decryptBody != null) {
123185
return DecryptAnnotationInfoBean.builder().decryptBodyMethod(decryptBody.value()).key(decryptBody.otherKey()).build();
124186
}
125187
}
126-
if (method.isAnnotationPresent(DESDecryptBody.class)) {
127-
DESDecryptBody decryptBody = methodParameter.getMethodAnnotation(DESDecryptBody.class);
188+
if (annotatedElement.isAnnotationPresent(DESDecryptBody.class)) {
189+
DESDecryptBody decryptBody = annotatedElement.getAnnotation(DESDecryptBody.class);
128190
if (decryptBody != null) {
129191
return DecryptAnnotationInfoBean.builder().decryptBodyMethod(DecryptBodyMethod.DES).key(decryptBody.key()).build();
130192
}
131193
}
132-
if (method.isAnnotationPresent(AESDecryptBody.class)) {
133-
AESDecryptBody decryptBody = methodParameter.getMethodAnnotation(AESDecryptBody.class);
194+
if (annotatedElement.isAnnotationPresent(AESDecryptBody.class)) {
195+
AESDecryptBody decryptBody = annotatedElement.getAnnotation(AESDecryptBody.class);
134196
if (decryptBody != null) {
135197
return DecryptAnnotationInfoBean.builder().decryptBodyMethod(DecryptBodyMethod.AES).key(decryptBody.key()).build();
136198
}
137199
}
138-
if (method.isAnnotationPresent(RSADecryptBody.class)) {
139-
RSADecryptBody decryptBody = methodParameter.getMethodAnnotation(RSADecryptBody.class);
200+
if (annotatedElement.isAnnotationPresent(RSADecryptBody.class)) {
201+
RSADecryptBody decryptBody = annotatedElement.getAnnotation(RSADecryptBody.class);
140202
if (decryptBody != null) {
141203
return DecryptAnnotationInfoBean.builder().decryptBodyMethod(DecryptBodyMethod.RSA).key(decryptBody.key()).rsaKeyType(decryptBody.type()).build();
142204
}
143205
}
144206
return null;
145207
}
146208

147-
/**
148-
* 获取类控制器上的加密注解信息
149-
*
150-
* @param clazz 控制器类
151-
* @return 加密注解信息
152-
*/
153-
private DecryptAnnotationInfoBean getClassAnnotation(Class<?> clazz) {
154-
Annotation[] annotations = clazz.getDeclaredAnnotations();
155-
if (annotations.length > 0) {
156-
for (Annotation annotation : annotations) {
157-
if (annotation instanceof DecryptBody) {
158-
DecryptBody decryptBody = (DecryptBody) annotation;
159-
return DecryptAnnotationInfoBean.builder().decryptBodyMethod(decryptBody.value()).key(decryptBody.otherKey()).build();
160-
}
161-
if (annotation instanceof DESDecryptBody) {
162-
return DecryptAnnotationInfoBean.builder().decryptBodyMethod(DecryptBodyMethod.DES).key(((DESDecryptBody) annotation).key()).build();
163-
}
164-
if (annotation instanceof AESDecryptBody) {
165-
return DecryptAnnotationInfoBean.builder().decryptBodyMethod(DecryptBodyMethod.AES).key(((AESDecryptBody) annotation).key()).build();
166-
}
167-
}
168-
}
169-
return null;
170-
}
171-
172209

173210
/**
174211
* 选择加密方式并进行解密

0 commit comments

Comments
 (0)