防重放攻击

This commit is contained in:
cwchen 2025-09-04 18:30:42 +08:00
parent e5179ac441
commit 622e6a0eb0
2 changed files with 85 additions and 25 deletions

View File

@ -273,8 +273,12 @@ public class RequestCoverFilter implements Filter {
/**
* 查询字符串包装类
*/
/**
* 查询字符串包装类支持嵌套参数格式
*/
private static class QueryStringRequestWrapper extends HttpServletRequestWrapper {
private final String queryString;
private Map<String, String[]> cachedParameterMap;
public QueryStringRequestWrapper(HttpServletRequest request, String queryString) {
super(request);
@ -288,45 +292,101 @@ public class RequestCoverFilter implements Filter {
@Override
public String getParameter(String name) {
// 解析queryString获取参数值
if (queryString != null) {
String[] pairs = queryString.split("&");
for (String pair : pairs) {
String[] keyValue = pair.split("=");
if (keyValue.length == 2 && keyValue[0].equals(name)) {
return keyValue[1];
}
}
}
return super.getParameter(name);
String[] values = getParameterMap().get(name);
return (values != null && values.length > 0) ? values[0] : null;
}
@Override
public Map<String, String[]> getParameterMap() {
// 解析queryString为参数Map
Map<String, String[]> parameterMap = new HashMap<>();
if (queryString != null) {
String[] pairs = queryString.split("&");
for (String pair : pairs) {
String[] keyValue = pair.split("=");
if (keyValue.length == 2) {
parameterMap.put(keyValue[0], new String[]{keyValue[1]});
}
}
if (cachedParameterMap == null) {
cachedParameterMap = parseNestedQueryString(queryString);
}
return parameterMap;
return cachedParameterMap;
}
@Override
public Enumeration<String> getParameterNames() {
Map<String, String[]> parameterMap = getParameterMap();
return Collections.enumeration(parameterMap.keySet());
return Collections.enumeration(getParameterMap().keySet());
}
@Override
public String[] getParameterValues(String name) {
return getParameterMap().get(name);
}
/**
* 解析嵌套查询字符串为Map支持 params[beginTime] 格式
*/
private Map<String, String[]> parseNestedQueryString(String queryString) {
Map<String, String[]> parameterMap = new HashMap<>();
if (queryString != null) {
try {
// 先URL解码
String decodedQueryString = java.net.URLDecoder.decode(queryString, StandardCharsets.UTF_8.name());
String[] pairs = decodedQueryString.split("&");
for (String pair : pairs) {
String[] keyValue = pair.split("=", 2);
if (keyValue.length == 2) {
String key = keyValue[0];
String value = keyValue[1];
// 处理嵌套参数格式 params[beginTime]
if (key.startsWith("params[") && key.endsWith("]")) {
// 提取嵌套参数名如从 "params[beginTime]" 提取 "beginTime"
String nestedKey = key.substring(7, key.length() - 1);
// 将嵌套参数转换为 params. 前缀的参数
String paramsKey = nestedKey;
parameterMap.put(paramsKey, new String[]{value});
} else {
// 普通参数处理
if (parameterMap.containsKey(key)) {
String[] existingValues = parameterMap.get(key);
String[] newValues = Arrays.copyOf(existingValues, existingValues.length + 1);
newValues[existingValues.length] = value;
parameterMap.put(key, newValues);
} else {
parameterMap.put(key, new String[]{value});
}
}
}
}
} catch (Exception e) {
log.warn("解析嵌套查询字符串失败,使用简单解析: {}", e.getMessage());
return parseSimpleQueryString(queryString);
}
}
return parameterMap;
}
/**
* 简单解析查询字符串备用方案
*/
private Map<String, String[]> parseSimpleQueryString(String queryString) {
Map<String, String[]> parameterMap = new HashMap<>();
if (queryString != null) {
String[] pairs = queryString.split("&");
for (String pair : pairs) {
String[] keyValue = pair.split("=", 2);
if (keyValue.length == 2) {
String key = keyValue[0];
String value = keyValue[1];
if (parameterMap.containsKey(key)) {
String[] existingValues = parameterMap.get(key);
String[] newValues = Arrays.copyOf(existingValues, existingValues.length + 1);
newValues[existingValues.length] = value;
parameterMap.put(key, newValues);
} else {
parameterMap.put(key, new String[]{value});
}
}
}
}
return parameterMap;
}
}
}

View File

@ -172,7 +172,7 @@ public class ReplayAttackFilter implements Filter {
// 构建待签名字符串
String signString = buildSignString(encryptUserId, timestamp, requestUrl, request.getMethod());
System.err.println(signString);
// 使用HMAC-SHA256计算签名
String calculatedSignature = calculateHMAC(signString, encryptSecret);