修改加解密逻辑,允许使用通配符进行过滤

This commit is contained in:
wzy-warehouse
2026-05-18 10:16:26 +08:00
parent 2b40f2e13b
commit e4e3a09c47
3 changed files with 50 additions and 20 deletions
@@ -3,6 +3,7 @@ package com.gis.xian.filter;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference; import com.alibaba.fastjson2.TypeReference;
import com.gis.xian.config.CryptoProperties; import com.gis.xian.config.CryptoProperties;
import com.gis.xian.utils.PathMatcherUtils;
import com.gis.xian.utils.safety.SM2Utils; import com.gis.xian.utils.safety.SM2Utils;
import com.gis.xian.utils.safety.SM4Utils; import com.gis.xian.utils.safety.SM4Utils;
import com.gis.xian.wrapper.Sm4KeyHolder; import com.gis.xian.wrapper.Sm4KeyHolder;
@@ -85,15 +86,10 @@ public class DecryptFilter implements Filter {
} }
/** /**
* 检查是否为无需解密的路径 * 检查是否为无需解密的路径(支持通配符匹配)
*/ */
private boolean isNoDecryptPath(String requestUri) { private boolean isNoDecryptPath(String requestUri) {
for (String path : cryptoProperties.getNoDecryptPaths()) { return PathMatcherUtils.matches(requestUri, cryptoProperties.getNoDecryptPaths());
if (requestUri.contains(path)) {
return true;
}
}
return false;
} }
/** /**
@@ -0,0 +1,38 @@
package com.gis.xian.utils;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import java.util.List;
/**
* 路径匹配工具类
* 支持 Ant 风格通配符:
* - ? 匹配一个字符
* - * 匹配零个或多个字符(不包括路径分隔符)
* - ** 匹配零个或多个目录
*/
public class PathMatcherUtils {
private static final PathMatcher pathMatcher = new AntPathMatcher();
/**
* 检查请求路径是否匹配给定的模式列表
*
* @param requestUri 请求URI
* @param patterns 通配符模式列表
* @return 如果匹配返回true,否则返回false
*/
public static boolean matches(String requestUri, List<String> patterns) {
if (patterns == null || patterns.isEmpty()) {
return false;
}
for (String pattern : patterns) {
if (pathMatcher.match(pattern, requestUri)) {
return true;
}
}
return false;
}
}
@@ -2,6 +2,7 @@ package com.gis.xian.wrapper;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.gis.xian.config.CryptoProperties; import com.gis.xian.config.CryptoProperties;
import com.gis.xian.utils.PathMatcherUtils;
import com.gis.xian.utils.safety.SM4Utils; import com.gis.xian.utils.safety.SM4Utils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
@@ -29,7 +30,7 @@ public class EncryptResponseAdvice implements ResponseBodyAdvice<Object> {
private CryptoProperties cryptoProperties; private CryptoProperties cryptoProperties;
/** /**
* 判断是否需要加密:排除特定路径,其余全部加密 * 判断是否需要加密:排除特定路径,其余全部加密(支持通配符匹配)
*/ */
@Override @Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
@@ -41,19 +42,12 @@ public class EncryptResponseAdvice implements ResponseBodyAdvice<Object> {
HttpServletRequest request = attributes.getRequest(); HttpServletRequest request = attributes.getRequest();
String requestUri = request.getRequestURI(); String requestUri = request.getRequestURI();
// 检查是否为无需加密的路径 // 检查是否为无需加密的路径(支持通配符)
for (String path : cryptoProperties.getNoEncryptPaths()) { return !PathMatcherUtils.matches(requestUri, cryptoProperties.getNoEncryptPaths());
if (requestUri.contains(path)) {
return false; // 排除路径,不加密
}
}
// 其余路径均需要加密
return true;
} }
/** /**
* 响应体加密逻辑(保持不变) * 响应体加密逻辑
*/ */
@Override @Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
@@ -61,15 +55,17 @@ public class EncryptResponseAdvice implements ResponseBodyAdvice<Object> {
ServerHttpRequest request, ServerHttpResponse response) { ServerHttpRequest request, ServerHttpResponse response) {
try { try {
String sm4Key = Sm4KeyHolder.getSm4Key(); String sm4Key = Sm4KeyHolder.getSm4Key();
// 如果SM4密钥不存在,直接返回原始数据(不加密)
if (sm4Key == null || sm4Key.length() != 32) { if (sm4Key == null || sm4Key.length() != 32) {
throw new RuntimeException("SM4密钥不存在或格式错误,无法加密响应"); return body;
} }
String plaintext = objectMapper.writeValueAsString(body); String plaintext = objectMapper.writeValueAsString(body);
String encryptedText = SM4Utils.encrypt(sm4Key, plaintext); String encryptedText = SM4Utils.encrypt(sm4Key, plaintext);
return encryptedText; return encryptedText;
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("响应数据加密失败: " + e.getMessage(), e); // 加密失败时返回原始数据,避免影响业务
return body;
} finally { } finally {
Sm4KeyHolder.clear(); // 清除线程本地存储,避免内存泄漏 Sm4KeyHolder.clear(); // 清除线程本地存储,避免内存泄漏
} }