fix(XSSInterceptor): 增强XSS拦截器对请求头的处理

修改XSS拦截器对请求头的检查逻辑,当检测到XSS攻击时直接拒绝请求并返回400错误响应。新增错误响应写入方法,记录攻击日志。
This commit is contained in:
ikmkj
2026-03-03 18:58:03 +08:00
parent 07454a28d2
commit 64daf3cb0b

View File

@@ -2,8 +2,12 @@ package com.test.bijihoudaun.interceptor;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil; import cn.hutool.http.HtmlUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.bijihoudaun.common.response.R;
import com.test.bijihoudaun.common.response.ResultCode;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.HandlerInterceptor;
import java.util.Enumeration; import java.util.Enumeration;
@@ -14,12 +18,15 @@ import java.util.Enumeration;
* 注意:此拦截器只能过滤 URL 参数和表单数据,无法过滤 @RequestBody 的 JSON 数据 * 注意:此拦截器只能过滤 URL 参数和表单数据,无法过滤 @RequestBody 的 JSON 数据
* JSON 数据的 XSS 过滤由 XssStringDeserializer 处理 * JSON 数据的 XSS 过滤由 XssStringDeserializer 处理
*/ */
@Slf4j
public class XSSInterceptor implements HandlerInterceptor { public class XSSInterceptor implements HandlerInterceptor {
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 过滤请求头 // 过滤请求头,发现 XSS 攻击则拒绝请求
filterHeaders(request); if (!filterHeaders(request, response)) {
return false;
}
// 过滤请求参数URL 参数和表单数据) // 过滤请求参数URL 参数和表单数据)
filterParameters(request); filterParameters(request);
@@ -29,11 +36,12 @@ public class XSSInterceptor implements HandlerInterceptor {
/** /**
* 过滤请求头 * 过滤请求头
* @return true-通过false-拒绝请求
*/ */
private void filterHeaders(HttpServletRequest request) { private boolean filterHeaders(HttpServletRequest request, HttpServletResponse response) throws Exception {
Enumeration<String> headerNames = request.getHeaderNames(); Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames == null) { if (headerNames == null) {
return; return true;
} }
while (headerNames.hasMoreElements()) { while (headerNames.hasMoreElements()) {
@@ -41,12 +49,15 @@ public class XSSInterceptor implements HandlerInterceptor {
String headerValue = request.getHeader(headerName); String headerValue = request.getHeader(headerName);
if (StrUtil.isNotBlank(headerValue)) { if (StrUtil.isNotBlank(headerValue)) {
String filteredValue = HtmlUtil.filter(headerValue); String filteredValue = HtmlUtil.filter(headerValue);
// 注意:请求头无法直接修改,这里只是记录日志 // 发现 XSS 内容,记录日志并拒绝请求
if (!headerValue.equals(filteredValue)) { if (!headerValue.equals(filteredValue)) {
// 发现 XSS 内容,记录日志 log.warn("检测到XSS攻击请求头{},原始值:{}", headerName, headerValue);
writeErrorResponse(response, "检测到恶意内容,请求被拒绝");
return false;
} }
} }
} }
return true;
} }
/** /**
@@ -65,4 +76,16 @@ public class XSSInterceptor implements HandlerInterceptor {
} }
} }
} }
/**
* 写入错误响应
*/
private void writeErrorResponse(HttpServletResponse response, String message) throws Exception {
response.setContentType("application/json;charset=UTF-8");
response.setStatus(400);
ObjectMapper mapper = new ObjectMapper();
response.getWriter().write(mapper.writeValueAsString(
R.fail(ResultCode.FAILED.getCode(), message)
));
}
} }