fix(XSSInterceptor): 增强XSS拦截器对请求头的处理
修改XSS拦截器对请求头的检查逻辑,当检测到XSS攻击时直接拒绝请求并返回400错误响应。新增错误响应写入方法,记录攻击日志。
This commit is contained in:
@@ -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)
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user