Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
dengli
2023-12-16 18:59:09 +08:00
7 changed files with 366 additions and 0 deletions

View File

@@ -10,6 +10,7 @@ import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import cn.stock.market.web.annotations.EncryptFilter;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@@ -137,6 +138,7 @@ public class StockApiController {
@RequestMapping({"getINDStockList.do"})
@ApiOperation(value = "印度股票列表", httpMethod = "GET")
@ResponseBody
@EncryptFilter(decryptRequest = false)
public ServerResponse getINDStockList(@RequestParam("pageSize") Integer pageSize, @RequestParam("pageNum") Integer pageNum) throws IOException {
return ServerResponse.createBySuccess(InvestingInvokerApis.of().__page(pageNum, pageSize));
}

View File

@@ -0,0 +1,21 @@
package cn.stock.market.web.annotations;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface EncryptFilter {
/**
* 对入参是否解密
*
* @return
*/
boolean decryptRequest() default true;
/**
* 对出参是否加密
*/
boolean encryptResponse() default true;
}

View File

@@ -0,0 +1,103 @@
package cn.stock.market.web.handler;
import cn.stock.market.utils.AESUtil;
import cn.stock.market.utils.StreamUtil;
import cn.stock.market.web.annotations.EncryptFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
/**
* 全局请求入参RequestBody处理器
*
*/
@ControllerAdvice
@Slf4j
public class GlobalRequestBodyHandler extends RequestBodyAdviceAdapter {
/**
* 该方法用于判断当前请求是否要执行beforeBodyRead方法
*
* @param methodParameter handler方法的参数对象
* @param targetType handler方法的参数类型
* @param converterType 将会使用到的Http消息转换器类类型
* @return 返回true则会执行beforeBodyRead
*/
@Override
public boolean supports(MethodParameter methodParameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType) {
Method method = methodParameter.getMethod();
if (Objects.nonNull(method)) {
EncryptFilter encryptFilter = method.getAnnotation(EncryptFilter.class);
if (Objects.nonNull(encryptFilter)) {
return encryptFilter.decryptRequest();
}
}
return false;
}
/**
* 在Http消息转换器执转换之前执行
*
* @param inputMessage 客户端的请求数据
* @param methodParameter handler方法的参数对象
* @param targetType handler方法的参数类型
* @param converterType 将会使用到的Http消息转换器类类型
* @return 返回 一个自定义的HttpInputMessage
*/
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter methodParameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
// 读取加密的请求体
InputStream body = inputMessage.getBody();
HttpHeaders headers = inputMessage.getHeaders();
headers.remove("Content-Length");
String s = StreamUtil.getBodyString(body);
log.info("解密前请求body:" + s);
if (StringUtils.isEmpty(s)){
return inputMessage;
}
Method method = methodParameter.getMethod();
if (Objects.isNull(method)) {
return inputMessage;
}
// 解密请求
EncryptFilter encryptFilter = method.getAnnotation(EncryptFilter.class);
if (Objects.nonNull(encryptFilter) && encryptFilter.decryptRequest()) {
// 使用AES解密
String bodyDec = AESUtil.decrypt(s);
log.info("解密后请求body:" + bodyDec);
if (!StringUtils.isEmpty(bodyDec)) {
// 使用解密后的数据,构造新的读取流
InputStream inputStream = new ByteArrayInputStream(bodyDec.getBytes(StandardCharsets.UTF_8));
return new HttpInputMessage() {
@Override
public HttpHeaders getHeaders() {
return inputMessage.getHeaders();
}
@Override
public InputStream getBody() {
return inputStream;
}
};
}
}
return inputMessage;
}
}

View File

@@ -0,0 +1,67 @@
package cn.stock.market.web.handler;
import cn.stock.market.utils.AESUtil;
import cn.stock.market.utils.PropertiesUtil;
import cn.stock.market.web.annotations.EncryptFilter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
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.reflect.Method;
import java.util.Objects;
/**
* 全局响应结果ResponseBody处理器
*
*/
@ControllerAdvice
@Slf4j
public class GlobalResponseBodyHandler implements ResponseBodyAdvice {
private ObjectMapper objectMapper = new ObjectMapper();
public GlobalResponseBodyHandler(){
}
@Override
@SuppressWarnings("NullableProblems") // 避免 IDEA 警告
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@Override
@SuppressWarnings("NullableProblems") // 避免 IDEA 警告
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
Method method = returnType.getMethod();
if (Objects.isNull(body) || Objects.isNull(method)) {
return body;
}
log.info("处理请求地址:{} 的返回值", request.getURI());
//获取请求数据
String srcData = null;
try {
srcData = objectMapper.writeValueAsString(body);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
log.info("加密前响应body={}", srcData);
EncryptFilter encryptFilter = method.getAnnotation(EncryptFilter.class);
if (Objects.nonNull(encryptFilter) && encryptFilter.encryptResponse()) {
//加密
String returnStr = AESUtil.encrypt(srcData);
log.info("加密后响应body:" + returnStr);
//添加 encrypt 告诉前端数据已加密
return returnStr;
}
return body;
}
}