| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- package cn.licoy.encryptbody.advice;
- import cn.licoy.encryptbody.annotation.encrypt.*;
- import cn.licoy.encryptbody.bean.EncryptAnnotationInfoBean;
- import cn.licoy.encryptbody.enums.EncryptBodyMethod;
- import cn.licoy.encryptbody.enums.SHAEncryptType;
- import cn.licoy.encryptbody.exception.EncryptBodyFailException;
- import cn.licoy.encryptbody.exception.EncryptMethodNotFoundException;
- import cn.licoy.encryptbody.util.*;
- import com.fasterxml.jackson.core.JsonProcessingException;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import cn.licoy.encryptbody.config.EncryptBodyConfig;
- import jodd.util.ReflectUtil;
- import lombok.SneakyThrows;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.core.MethodParameter;
- import org.springframework.core.annotation.Order;
- import org.springframework.http.MediaType;
- import org.springframework.http.server.ServerHttpRequest;
- import org.springframework.http.server.ServerHttpResponse;
- import org.springframework.web.bind.annotation.ControllerAdvice;
- import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
- import java.lang.annotation.Annotation;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import java.util.stream.Collectors;
- /**
- * 响应数据的加密处理<br>
- * 本类只对控制器参数中含有<strong>{@link org.springframework.web.bind.annotation.ResponseBody}</strong>
- * 或者控制类上含有<strong>{@link org.springframework.web.bind.annotation.RestController}</strong>
- * 以及package为<strong><code>cn.licoy.encryptbody.annotation.encrypt</code></strong>下的注解有效
- *
- * @author licoy.cn
- * @version 2018/9/4
- * @see ResponseBodyAdvice
- */
- @Order(1)
- @ControllerAdvice
- @Slf4j
- public class EncryptResponseBodyAdvice implements ResponseBodyAdvice {
- private final ObjectMapper objectMapper;
- private final EncryptBodyConfig config;
- @Value("${encrypt.enable}")
- private boolean enableEncrypt;
- @Autowired
- public EncryptResponseBodyAdvice(ObjectMapper objectMapper, EncryptBodyConfig config) {
- this.objectMapper = objectMapper;
- this.config = config;
- }
- @Override
- public boolean supports(MethodParameter returnType, Class converterType) {
- if (!enableEncrypt) return false;
- Annotation[] annotations = returnType.getDeclaringClass().getAnnotations();
- if (annotations != null && annotations.length > 0) {
- for (Annotation annotation : annotations) {
- if (annotation instanceof EncryptBody ||
- annotation instanceof AESEncryptBody ||
- annotation instanceof DESEncryptBody ||
- annotation instanceof RSAEncryptBody ||
- annotation instanceof MD5EncryptBody ||
- annotation instanceof SHAEncryptBody) {
- return true;
- }
- }
- }
- if (Arrays.stream(ReflectUtil.getSuperclasses(returnType.getDeclaringClass()))
- .flatMap(clazz -> Arrays.stream(clazz.getAnnotations()))
- .anyMatch(annotation -> annotation instanceof EncryptBody ||
- annotation instanceof AESEncryptBody ||
- annotation instanceof DESEncryptBody ||
- annotation instanceof RSAEncryptBody ||
- annotation instanceof MD5EncryptBody ||
- annotation instanceof SHAEncryptBody)) {
- return true;
- }
- return returnType.getMethod().isAnnotationPresent(EncryptBody.class) ||
- returnType.getMethod().isAnnotationPresent(AESEncryptBody.class) ||
- returnType.getMethod().isAnnotationPresent(DESEncryptBody.class) ||
- returnType.getMethod().isAnnotationPresent(RSAEncryptBody.class) ||
- returnType.getMethod().isAnnotationPresent(MD5EncryptBody.class) ||
- returnType.getMethod().isAnnotationPresent(SHAEncryptBody.class);
- }
- @SneakyThrows
- @Override
- public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
- Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
- if (body == null) return null;
- response.getHeaders().add("Content-Encrypted", "true");
- String str = null;
- try {
- str = objectMapper.writeValueAsString(body);
- } catch (JsonProcessingException e) {
- e.printStackTrace();
- }
- EncryptAnnotationInfoBean classAnnotation = getClassAnnotation(returnType.getDeclaringClass());
- if (classAnnotation != null) {
- return switchEncrypt(str, classAnnotation);
- }
- EncryptAnnotationInfoBean methodAnnotation = getMethodAnnotation(returnType);
- if (methodAnnotation != null) {
- return switchEncrypt(str, methodAnnotation);
- }
- throw new EncryptBodyFailException();
- }
- /**
- * 获取方法控制器上的加密注解信息
- *
- * @param methodParameter 控制器方法
- * @return 加密注解信息
- */
- private EncryptAnnotationInfoBean getMethodAnnotation(MethodParameter methodParameter) {
- if (methodParameter.getMethod().isAnnotationPresent(EncryptBody.class)) {
- EncryptBody encryptBody = methodParameter.getMethodAnnotation(EncryptBody.class);
- return EncryptAnnotationInfoBean.builder()
- .encryptBodyMethod(encryptBody.value())
- .key(encryptBody.otherKey())
- .shaEncryptType(encryptBody.shaType())
- .build();
- }
- if (methodParameter.getMethod().isAnnotationPresent(MD5EncryptBody.class)) {
- return EncryptAnnotationInfoBean.builder()
- .encryptBodyMethod(EncryptBodyMethod.MD5)
- .build();
- }
- if (methodParameter.getMethod().isAnnotationPresent(SHAEncryptBody.class)) {
- return EncryptAnnotationInfoBean.builder()
- .encryptBodyMethod(EncryptBodyMethod.SHA)
- .shaEncryptType(methodParameter.getMethodAnnotation(SHAEncryptBody.class).value())
- .build();
- }
- if (methodParameter.getMethod().isAnnotationPresent(DESEncryptBody.class)) {
- return EncryptAnnotationInfoBean.builder()
- .encryptBodyMethod(EncryptBodyMethod.DES)
- .key(methodParameter.getMethodAnnotation(DESEncryptBody.class).otherKey())
- .build();
- }
- if (methodParameter.getMethod().isAnnotationPresent(AESEncryptBody.class)) {
- return EncryptAnnotationInfoBean.builder()
- .encryptBodyMethod(EncryptBodyMethod.AES)
- .key(methodParameter.getMethodAnnotation(AESEncryptBody.class).otherKey())
- .build();
- }
- return null;
- }
- /**
- * 获取类控制器上的加密注解信息
- *
- * @param clazz 控制器类
- * @return 加密注解信息
- */
- private EncryptAnnotationInfoBean getClassAnnotation(Class clazz) {
- List<Annotation> annotations = new ArrayList<>(Arrays.asList(clazz.getSuperclass().getDeclaredAnnotations()));
- annotations.addAll(Arrays.asList(clazz.getDeclaredAnnotations()));
- for (Annotation annotation : annotations) {
- if (annotation instanceof EncryptBody) {
- EncryptBody encryptBody = (EncryptBody) annotation;
- return EncryptAnnotationInfoBean.builder()
- .encryptBodyMethod(encryptBody.value())
- .key(encryptBody.otherKey())
- .shaEncryptType(encryptBody.shaType())
- .build();
- }
- if (annotation instanceof MD5EncryptBody) {
- return EncryptAnnotationInfoBean.builder()
- .encryptBodyMethod(EncryptBodyMethod.MD5)
- .build();
- }
- if (annotation instanceof SHAEncryptBody) {
- return EncryptAnnotationInfoBean.builder()
- .encryptBodyMethod(EncryptBodyMethod.SHA)
- .shaEncryptType(((SHAEncryptBody) annotation).value())
- .build();
- }
- if (annotation instanceof DESEncryptBody) {
- return EncryptAnnotationInfoBean.builder()
- .encryptBodyMethod(EncryptBodyMethod.DES)
- .key(((DESEncryptBody) annotation).otherKey())
- .build();
- }
- if (annotation instanceof AESEncryptBody) {
- return EncryptAnnotationInfoBean.builder()
- .encryptBodyMethod(EncryptBodyMethod.AES)
- .key(((AESEncryptBody) annotation).otherKey())
- .build();
- }
- }
- return null;
- }
- /**
- * 选择加密方式并进行加密
- *
- * @param formatStringBody 目标加密字符串
- * @param infoBean 加密信息
- * @return 加密结果
- */
- private String switchEncrypt(String formatStringBody, EncryptAnnotationInfoBean infoBean) throws Exception {
- EncryptBodyMethod method = infoBean.getEncryptBodyMethod();
- if (method == null) {
- throw new EncryptMethodNotFoundException();
- }
- if (method == EncryptBodyMethod.MD5) {
- return MD5EncryptUtil.encrypt(formatStringBody);
- }
- if (method == EncryptBodyMethod.SHA) {
- SHAEncryptType shaEncryptType = infoBean.getShaEncryptType();
- if (shaEncryptType == null) shaEncryptType = SHAEncryptType.SHA256;
- return SHAEncryptUtil.encrypt(formatStringBody, shaEncryptType);
- }
- String key = infoBean.getKey();
- if (method == EncryptBodyMethod.DES) {
- key = CheckUtils.checkAndGetKey(config.getDesKey(), key, "DES-KEY");
- return DESEncryptUtil.encrypt(formatStringBody, key);
- }
- if (method == EncryptBodyMethod.AES) {
- key = CheckUtils.checkAndGetKey(config.getAesKey(), key, "AES-KEY");
- return AESEncryptUtil.encrypt(formatStringBody, key);
- }
- throw new EncryptBodyFailException();
- }
- }
|