1. 框架优化

2. 接口响应数据增加AES加密拦截
master
陈峰 1 year ago
parent 8fa20f37f1
commit 12e0025ef6
  1. 394
      framework-core/pom.xml
  2. 2
      framework-core/src/main/java/com/unionmed/framework/crypto/AES.java
  3. 76
      framework-core/src/main/java/com/unionmed/framework/spring/mvc/response/DecryptRequestBodyAdvice.java
  4. 30
      framework-core/src/main/java/com/unionmed/framework/spring/mvc/response/RequestResponseBodyCryptProperties.java
  5. 10
      framework-core/src/main/java/com/unionmed/framework/spring/mvc/response/ResponseBodyConfiguration.java
  6. 26
      framework-core/src/main/java/com/unionmed/framework/spring/mvc/response/interceptor/EncryptionResponseBodyInterceptor.java
  7. 2
      framework-orm/pom.xml
  8. 2
      framework-test/pom.xml
  9. 2
      pom.xml

@ -2,200 +2,206 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.unionmed</groupId>
<artifactId>unionmed-framework</artifactId>
<version>0.0.11</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.unionmed</groupId>
<artifactId>framework-core</artifactId>
<name>framework-core</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!-- alibaba -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!-- spring framework -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<artifactId>unionmed-framework</artifactId>
<version>0.0.12</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.unionmed</groupId>
<artifactId>framework-core</artifactId>
<name>framework-core</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!-- alibaba -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!-- spring framework -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- minio 相关依赖 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>io.github.yedaxia</groupId>
<artifactId>japidocs</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<!--在引用时请在maven中央仓库搜索2.X最新版本号-->
</dependency>
<dependency>
<groupId>com.github.isrsal</groupId>
<artifactId>spring-mvc-logger</artifactId>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Google -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>com</groupId>
<artifactId>com.util</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxnetty</artifactId>
</dependency>
<dependency>
<groupId>com.mks.api</groupId>
<artifactId>mksapi-jar</artifactId>
</dependency>
<!-- Apache: http-client -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
<!-- 加/解 密 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
<build>
<finalName>${project.name}-${project.parent.version}</finalName>
<!--<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- minio 相关依赖 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>io.github.yedaxia</groupId>
<artifactId>japidocs</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<!--在引用时请在maven中央仓库搜索2.X最新版本号-->
</dependency>
<dependency>
<groupId>com.github.isrsal</groupId>
<artifactId>spring-mvc-logger</artifactId>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Google -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>com</groupId>
<artifactId>com.util</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxnetty</artifactId>
</dependency>
<dependency>
<groupId>com.mks.api</groupId>
<artifactId>mksapi-jar</artifactId>
</dependency>
<!-- Apache: http-client -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
<!-- 加/解 密 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.name}-${project.parent.version}</finalName>
<!--<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<mainClass>com.unionmed.framework.springboot.Application</mainClass>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>-->
<!-- maven打包:将指定资源文件打包进Jar中。-->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<mainClass>com.unionmed.framework.springboot.Application</mainClass>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>-->
<!-- maven打包:将指定资源文件打包进Jar中。-->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

@ -28,7 +28,7 @@ public class AES {
SecretKeySpec skSpec = new SecretKeySpec(toUtf8Bytes(sk), ALGORITHM);
Cipher cipher = Cipher.getInstance(PADDING);
cipher.init(Cipher.ENCRYPT_MODE, skSpec, ivSpec);
return Base64.encodeBase64String(cipher.doFinal(value.getBytes()));
return Base64.encodeBase64String(cipher.doFinal(toUtf8Bytes(value)));
} catch (Exception ex) {
log.error("AES加密失败", ex);
return null;

@ -0,0 +1,76 @@
package com.unionmed.framework.spring.mvc.response;
import com.alibaba.fastjson.JSON;
import com.unionmed.framework.crypto.AES;
import com.unionmed.framework.http.HttpHeaders;
import com.unionmed.framework.util.ObjectUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
/**
* @author ianChen
* @date 2023/6/26 14:02
*/
@Slf4j
@ControllerAdvice
public class DecryptRequestBodyAdvice implements RequestBodyAdvice {
@Autowired
private RequestResponseBodyCryptProperties requestResponseBodyCryptProperties;
@Override
public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public HttpInputMessage beforeBodyRead(final HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
String body = IOUtils.toString(inputMessage.getBody(), HttpHeaders.CHARSET_UTF8);
if (ObjectUtils.notEmpty(body) && requestResponseBodyCryptProperties.isEnabled() && ObjectUtils.equalsIgnore(inputMessage.getHeaders().getFirst(HttpHeaders.X_DATA_CRYPT_E), HttpHeaders.X_DATA_CRYPT_E_VALUE_TRUE)) {
body = AES.decrypt(requestResponseBodyCryptProperties.getSk(), body.substring(0, 16), body.substring(16));
}
if (log.isDebugEnabled()) {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
log.debug("URI: {}, Method: {}", servletRequestAttributes.getRequest().getRequestURI(), servletRequestAttributes.getRequest().getMethod());
log.debug("Headers: {}", JSON.toJSONString(inputMessage.getHeaders().toSingleValueMap()));
log.debug("RequestParameter: {}", servletRequestAttributes.getRequest().getParameterMap() == null ? "" : JSON.toJSONString(servletRequestAttributes.getRequest().getParameterMap()));
log.debug("RequestBody: {}", body);
}
InputStream is = IOUtils.toInputStream(body, HttpHeaders.CHARSET_UTF8);
return new HttpInputMessage() {
@Override
public InputStream getBody() throws IOException {
return is;
}
@Override
public org.springframework.http.HttpHeaders getHeaders() {
return inputMessage.getHeaders();
}
};
}
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return body;
}
@Override
public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return body;
}
}

@ -0,0 +1,30 @@
package com.unionmed.framework.spring.mvc.response;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author ianChen
* @date 2023/6/26 14:06
*/
@ConfigurationProperties(prefix = "unionmed.web-mvc.body.crypt.aes")
public class RequestResponseBodyCryptProperties {
private boolean enabled = false;
private String sk;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getSk() {
return sk;
}
public void setSk(String sk) {
this.sk = sk;
}
}

@ -3,9 +3,9 @@ package com.unionmed.framework.spring.mvc.response;
import com.unionmed.framework.spring.mvc.response.datatemplate.DataTemplateResponseBodyInterceptor;
import com.unionmed.framework.spring.mvc.response.interceptor.EncryptionResponseBodyInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.context.annotation.ImportResource;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
@ -18,18 +18,18 @@ import java.util.List;
* @author ianChen
* @date 2023/6/25 15:25
*/
@EnableConfigurationProperties({RequestResponseBodyCryptProperties.class})
@Configuration
public class ResponseBodyConfiguration {
@Autowired
private Environment environment;
private RequestResponseBodyCryptProperties requestResponseBodyCryptProperties;
@Autowired
private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
// @Bean
public ResponseBodyProcessor responseBodyProcessor() {
ResponseBodyProcessorChain chain = new ResponseBodyProcessorChain();
chain.add(new DataTemplateResponseBodyInterceptor(), new EncryptionResponseBodyInterceptor(environment));
chain.add(new DataTemplateResponseBodyInterceptor(), new EncryptionResponseBodyInterceptor(requestResponseBodyCryptProperties));
return new ResponseBodyProcessor(requestMappingHandlerAdapter.getMessageConverters(), chain);//初始化过滤器
}

@ -7,10 +7,10 @@ import com.unionmed.framework.crypto.AES;
import com.unionmed.framework.http.HttpHeaders;
import com.unionmed.framework.spring.mvc.BaseReturn;
import com.unionmed.framework.spring.mvc.BaseReturnUtils;
import com.unionmed.framework.spring.mvc.response.RequestResponseBodyCryptProperties;
import com.unionmed.framework.util.Generators;
import com.unionmed.framework.util.ObjectUtils;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.Environment;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
@ -24,33 +24,23 @@ import java.util.Map;
*/
public class EncryptionResponseBodyInterceptor implements ResponseBodyInterceptor {
private final Environment environment;
private final String RESOURCE_PREFIX = "unionmed.web.response.body.crypt.aes";
private final String SK_KEY = RESOURCE_PREFIX + ".sk";
private final String ENABLED_KEY = RESOURCE_PREFIX + ".enabled";
private final boolean enabled;
private final String sk;
private final RequestResponseBodyCryptProperties properties;
public EncryptionResponseBodyInterceptor(Environment environment) {
this.environment = environment;
if (ObjectUtils.equalsIgnore(environment.getProperty(ENABLED_KEY), "true")) {
this.sk = environment.getProperty(SK_KEY);
if (ObjectUtils.isEmpty(sk))
public EncryptionResponseBodyInterceptor(RequestResponseBodyCryptProperties properties) {
this.properties = properties;
if (properties.isEnabled()) {
if (ObjectUtils.isEmpty(properties.getSk()))
throw new NullPointerException("AES SecretKey is empty");
this.enabled = true;
} else {
this.enabled = false;
this.sk = null;
}
}
@Override
public Object handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) {
if (!this.enabled || returnValue == null) return null;
if (!properties.isEnabled() || returnValue == null) return returnValue;
String value = webRequest.getHeader(HttpHeaders.X_DATA_CRYPT_E);
if (ObjectUtils.equalsIgnore(value, HttpHeaders.X_DATA_CRYPT_E_VALUE_TRUE)) {
returnValue = handleReturnValue(sk, Generators.randomMix(16), returnValue);
returnValue = handleReturnValue(properties.getSk(), Generators.randomMix(16), returnValue);
}
return returnValue;

@ -5,7 +5,7 @@
<parent>
<artifactId>unionmed-framework</artifactId>
<groupId>com.unionmed</groupId>
<version>0.0.11</version>
<version>0.0.12</version>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -5,7 +5,7 @@
<parent>
<groupId>com.unionmed</groupId>
<artifactId>unionmed-framework</artifactId>
<version>0.0.11</version>
<version>0.0.12</version>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -9,7 +9,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.unionmed</groupId>
<artifactId>unionmed-framework</artifactId>
<version>0.0.11</version>
<version>0.0.12</version>
<packaging>pom</packaging>
<name>unionmed-framework</name>

Loading…
Cancel
Save