package com.ruoyi.common.filter;
|
|
import cn.hutool.json.JSONObject;
|
import com.ruoyi.common.utils.Sm4Utils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.web.util.ContentCachingResponseWrapper;
|
|
import javax.servlet.*;
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletResponse;
|
import java.io.BufferedReader;
|
import java.io.IOException;
|
import java.nio.charset.StandardCharsets;
|
import java.rmi.ServerException;
|
|
public class SmCryptoFilter implements Filter {
|
|
private static final Logger logger = LoggerFactory.getLogger(SmCryptoFilter.class);
|
|
@Override
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
|
try {
|
// 设置请求和响应的编码为 UTF-8
|
request.setCharacterEncoding("UTF-8");
|
response.setCharacterEncoding("UTF-8");
|
response.setContentType("application/json;charset=UTF-8");
|
|
// 对请求进行解密
|
String decryptedRequestBody = decryptRequest(httpRequest);
|
logger.info("解密后数据={}", decryptedRequestBody);
|
// 处理解密后的请求体 CustomRequestWrapper为自定义请求包装器,请看下面实现
|
CustomRequestWrapper customRequestWrapper = new CustomRequestWrapper(httpRequest, decryptedRequestBody);
|
|
// 继续处理请求
|
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(httpResponse);
|
chain.doFilter(customRequestWrapper, responseWrapper);
|
|
// 获取并加密响应内容
|
byte[] content = responseWrapper.getContentAsByteArray();
|
String originalResponseBody = new String(content, StandardCharsets.UTF_8); // 关键修改
|
String encryptedResponseBody = encryptResponse(originalResponseBody);
|
|
responseWrapper.setContentType("application/json");
|
JSONObject result = new JSONObject();
|
result.put("data", encryptedResponseBody);
|
result.put("code", 200);
|
|
// 设置返回编码
|
responseWrapper.setCharacterEncoding("UTF-8");
|
// 写回客户端
|
responseWrapper.reset();
|
responseWrapper.getWriter().write(result.toString());
|
responseWrapper.copyBodyToResponse();
|
|
} catch (Exception e) {
|
logger.error("内部响应错误:{}", e.getMessage());
|
e.printStackTrace();
|
// 返回标准错误响应
|
httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
httpResponse.getWriter().write("Internal Server Error");
|
}
|
}
|
|
/**
|
* 解密 HTTP 请求的主体内容。
|
*
|
* @param request HTTP 请求对象
|
* @return 解密后的请求体字符串
|
* @throws IOException 如果读取或解密过程中发生错误
|
*/
|
private String decryptRequest(HttpServletRequest request) throws IOException {
|
// 先设置编码
|
request.setCharacterEncoding("UTF-8");
|
|
// 使用Reader读取,但确保使用了正确的编码
|
StringBuilder jb = new StringBuilder();
|
String line;
|
// 直接使用getReader(),此时应该使用UTF-8
|
try (BufferedReader reader = request.getReader()) {
|
while ((line = reader.readLine()) != null) {
|
jb.append(line);
|
}
|
}
|
|
String requestBody = jb.toString();
|
try {
|
return Sm4Utils.sm4DecryptUtil(requestBody);
|
} catch (Exception e) {
|
logger.error("参数解密失败,原始数据:{}", requestBody);
|
throw new ServerException("参数解密失败", e);
|
}
|
}
|
|
/**
|
* 加密 HTTP 响应的主体内容。
|
*
|
* @param response 原始响应体字符串
|
* @return 加密后的响应体字符串
|
*/
|
private String encryptResponse(String response) throws ServerException {
|
try {
|
return Sm4Utils.sm4EncryptUtil(response);
|
} catch (Exception e) {
|
throw new ServerException("参数解密失败:{}", e);
|
}
|
}
|
}
|