系统配置

This commit is contained in:
cwchen 2025-09-08 10:20:30 +08:00
parent 15b6bef566
commit a7ed6ae5ab
7 changed files with 534 additions and 104 deletions

View File

@ -19,7 +19,7 @@ server:
port: 8080
servlet:
# 应用的访问路径
context-path: /
context-path: /smartArchives
tomcat:
# tomcat的URI编码
uri-encoding: UTF-8
@ -34,7 +34,7 @@ server:
# 日志配置
logging:
level:
com.bonus: debug
com.bonus: info
org.springframework: warn
# 用户配置

View File

@ -62,7 +62,7 @@ public class RequestCoverFilter implements Filter {
// 处理不同类型的请求
if (contentType == null) {
log.info("请求头中无Content-Type信息处理URL参数。");
// log.info("请求头中无Content-Type信息处理URL参数。");
handleUrlParams(httpRequest, response, chain, integrality, encrypt);
} else if (contentType.contains(MediaType.APPLICATION_JSON_VALUE)) {
handleBodyRequest(httpRequest, response, chain, integrality, encrypt);

View File

@ -0,0 +1,175 @@
package com.bonus.common.utils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 安全验证的工具类
* 提供用于检测SQL注入特殊字符脚本注入等的工具方法
* 作者: GeYazhong
* 日期: 2021/11/23 10:54
*/
public class SafeUtil {
/**
* 安全SQL模式用于检测SQL注入的正则表达式
* 包含常见的SQL注入关键字和注释符号
*/
public final static String SAFE_SQL_PATTERN = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|"
+ "(\\b(select|update|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";
/**
* 安全脚本模式用于检测脚本注入的正则表达式
* 由于平台中setfilter中使用多个参数时用到&符号因此未包含&符号
*/
public final static String SAFE_SCRIPT_PATTERN =
"(\\||;|\\$|'|\\'|0x0d|0x0a|\\%27|\\%3B" +
"|<>|\\[\\]|\\(\\)|/|\"" +
"|script|alert|svg|confirm|prompt|onload" +
"|%3c|%3e|%2b|@|!|img|src" +
"|%|_)";
/**
* 检查特殊字符的正则表达式
* 用于判断字符串是否为数字字母下划线或汉字
*/
public static final String CHECK_SPECIAL = "^[\u4E00-\u9FA5A-Za-z_][\u4E00-\u9FA5A-Za-z0-9_]{0,}$";
/**
* 验证字符串是否包含SQL注入关键字
*
* @param mark 需要检查的字符串
* @return 如果包含SQL注入关键字返回true否则返回false
*/
public static boolean checkSafeSql(String mark) {
if (mark != null && !"".equals(mark)) {
return match(SAFE_SQL_PATTERN, mark.toLowerCase().trim());
}
return false;
}
/**
* 验证字符串是否包含特殊字符
*
* @param mark 需要检查的字符串
* @return 如果包含特殊字符返回true否则返回false
*/
public static boolean checkSpecial(String mark) {
if (mark != null && !"".equals(mark)) {
return match(SAFE_SQL_PATTERN, mark.toLowerCase().trim());
}
return false;
}
/**
* 验证字符串是否包含特殊脚本字符
*
* @param mark 需要检查的字符串
* @return 如果包含特殊脚本字符返回true否则返回false
*/
public static boolean checkScript(String mark) {
if (mark != null && !"".equals(mark)) {
return match(SAFE_SCRIPT_PATTERN, mark.toLowerCase().trim());
}
return false;
}
/**
* 执行正则表达式匹配
*
* @param pattern 正则表达式模式
* @param str 需要验证的字符串
* @return 如果匹配返回true否则返回false
*/
private static boolean match(String pattern, String str) {
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(str);
return m.find();
}
/**
* 检查字符串是否符合正则表达式
*
* @param regex 正则表达式
* @param orginal 需要检查的字符串
* @return 如果匹配返回true否则返回false
*/
private static boolean isMatch(String regex, String orginal) {
if (StringUtils.isEmpty(orginal)) {
return false;
}
Pattern pattern = Pattern.compile(regex);
Matcher isNum = pattern.matcher(orginal);
return isNum.matches();
}
/**
* 检查字符串是否为正整数
*
* @param orginal 需要检查的字符串
* @return 如果是正整数返回true否则返回false
*/
public static boolean isPositiveInteger(String orginal) {
return isMatch("^\\+{0,1}[1-9]\\d*", orginal);
}
/**
* 检查字符串是否为负整数
*
* @param orginal 需要检查的字符串
* @return 如果是负整数返回true否则返回false
*/
public static boolean isNegativeInteger(String orginal) {
return isMatch("^-[1-9]\\d*", orginal);
}
/**
* 检查字符串是否为整数
*
* @param orginal 需要检查的字符串
* @return 如果是整数返回true否则返回false
*/
public static boolean isWholeNumber(String orginal) {
return isMatch("[+-]{0,1}0", orginal) || isPositiveInteger(orginal) || isNegativeInteger(orginal);
}
/**
* 检查字符串是否为正小数
*
* @param orginal 需要检查的字符串
* @return 如果是正小数返回true否则返回false
*/
public static boolean isPositiveDecimal(String orginal) {
return isMatch("\\+{0,1}[0]\\.[1-9]*|\\+{0,1}[1-9]\\d*\\.\\d*", orginal);
}
/**
* 检查字符串是否为负小数
*
* @param orginal 需要检查的字符串
* @return 如果是负小数返回true否则返回false
*/
public static boolean isNegativeDecimal(String orginal) {
return isMatch("^-[0]\\.[1-9]*|^-[1-9]\\d*\\.\\d*", orginal);
}
/**
* 检查字符串是否为小数
*
* @param orginal 需要检查的字符串
* @return 如果是小数返回true否则返回false
*/
public static boolean isDecimal(String orginal) {
return isMatch("[-+]{0,1}\\d+\\.\\d*|[-+]{0,1}\\d*\\.\\d+", orginal);
}
/**
* 检查字符串是否为实数整数或小数
*
* @param orginal 需要检查的字符串
* @return 如果是实数返回true否则返回false
*/
public static boolean isRealNumber(String orginal) {
return isWholeNumber(orginal) || isDecimal(orginal);
}
}

View File

@ -1,6 +1,8 @@
package com.bonus.framework.config;
import java.util.concurrent.TimeUnit;
import com.bonus.framework.interceptor.ParamSecureHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -26,6 +28,12 @@ public class ResourcesConfig implements WebMvcConfigurer
@Autowired
private RepeatSubmitInterceptor repeatSubmitInterceptor;
@Autowired
private ParamSecureHandler paramSecureHandler;
/** 不需要拦截地址 "/logout",*/
public static final String[] EXCLUDEURLS = { "/login", "/refresh" };
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
@ -46,6 +54,11 @@ public class ResourcesConfig implements WebMvcConfigurer
public void addInterceptors(InterceptorRegistry registry)
{
registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
//自定义拦截器
registry.addInterceptor(paramSecureHandler)
.addPathPatterns("/**")
.excludePathPatterns(EXCLUDEURLS)
.order(-10);
}
/**

View File

@ -33,11 +33,11 @@ import org.springframework.stereotype.Component;
public class ReplayAttackFilter implements Filter {
static List<String> ignoreUrlPatterns = new ArrayList<>();
static {
ignoreUrlPatterns.add("/captchaImage");
ignoreUrlPatterns.add("/login");
ignoreUrlPatterns.add("/loginOut");
ignoreUrlPatterns.add("/getInfo");
ignoreUrlPatterns.add("/getRouters");
ignoreUrlPatterns.add("/smartArchives/captchaImage");
ignoreUrlPatterns.add("/smartArchives/login");
ignoreUrlPatterns.add("/smartArchives/logout");
ignoreUrlPatterns.add("/smartArchives/getInfo");
ignoreUrlPatterns.add("/smartArchives/getRouters");
}
@Autowired
@ -69,7 +69,6 @@ public class ReplayAttackFilter implements Filter {
boolean shouldIgnore = ignoreUrlPatterns.contains(requestURI);
if (shouldIgnore) {
// 忽略该请求的处理
System.out.println("忽略请求: " + requestURI);
chain.doFilter(request, response);
return;
}
@ -172,7 +171,6 @@ public class ReplayAttackFilter implements Filter {
// 构建待签名字符串
String signString = buildSignString(encryptUserId, timestamp, requestUrl, request.getMethod());
System.err.println(signString);
// 使用HMAC-SHA256计算签名
String calculatedSignature = calculateHMAC(signString, encryptSecret);

View File

@ -0,0 +1,241 @@
package com.bonus.framework.interceptor;
import com.alibaba.fastjson2.JSON;
import com.bonus.common.core.domain.AjaxResult;
import com.bonus.common.utils.SafeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
/**
* @author bonus
* @data 2023/2/6 17:22
* @description 安全参数验证
*/
@Slf4j
@Component
public class ParamSecureHandler implements AsyncHandlerInterceptor {
static List<String> ignoreUrlPatterns = new ArrayList<>();
static {
ignoreUrlPatterns.add("/smartArchives/captchaImage");
ignoreUrlPatterns.add("/smartArchives/login");
ignoreUrlPatterns.add("/smartArchives/logout");
ignoreUrlPatterns.add("/smartArchives/getInfo");
ignoreUrlPatterns.add("/smartArchives/getRouters");
}
private String rnd = null;
public static String ur = "/";
public static int max_length = 4;
private static Map<String, List<Double>> requestLogMap = null;
public boolean isFileUpload(HttpServletRequest request) {
String contentType = request.getContentType();
if (StringUtils.isEmpty(contentType)) {
return false;
}
if (contentType.contains(MULTIPART_FORM_DATA_VALUE)) {
return true;
}
return false;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 过滤部分请求
String requestUrl = request.getRequestURI();
boolean shouldIgnore = ignoreUrlPatterns.contains(requestUrl);
if (shouldIgnore) {
return true;
}
// 过滤文件上传功能
if (isFileUpload(request)) {
return true;
}
XssRequestWrapper requestWrapper = new XssRequestWrapper(request);
/**
* 校验参数是否合法
*/
if (!requestWrapper.isChecked()) {
log.error("输入值非法: queryString={}, body={}",
StringUtils.defaultString(requestWrapper.getQueryString(), "null"),
StringUtils.defaultString(requestWrapper.getReaderParam(), "null"));
returnJson(response, "输入值非法", 500);
return false;
}
// System.err.println(JSON.toJSONString(request.getParameterMap()));
/**
* 获取所有跳转路径参数保留传入下个界面
*/
Map<String, String[]> map = requestWrapper.getParameterMap();
boolean checkParameterMap = checkParameterMap(map, requestUrl);
if (!checkParameterMap) {
returnJson(response, "输入值非法", 500);
return false;
}
/**
* 检查数据流参数
*/
String readerParam = requestWrapper.getReaderParam();
// 判断是否是文件上传是不对流参数进行验证
String uplFile = "/upload", upImage = "/uploadFiles",path="/";
if (!requestUrl.contains(uplFile) && !requestUrl.contains(upImage) && !requestUrl.contains(path)) {
boolean checkReader = checkReader(readerParam, requestUrl);
if (!checkReader) {
returnJson(response, "不安全参数", 500);
return false;
}
}
return true;
}
private void returnJson(HttpServletResponse response, String msg, int code) {
response.reset();
PrintWriter writer = null;
response.setCharacterEncoding("UTF-8");
response.setContentType("applicatiopn/json;charset=utf-8");
AjaxResult a = AjaxResult.error(code, msg);
String res = JSON.toJSONString(a);
try {
writer = response.getWriter();
writer.println(res);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 检查所有页面输入的参数是否安全 request.getParameterMap()
*
* @param map
* @param requestUrl
*/
private boolean checkParameterMap(Map<String, String[]> map, String requestUrl) {
rnd = null;
if (map != null && map.size() > 0) {
Iterator<Map.Entry<String, String[]>> iterator = map.entrySet().iterator();
String value = "";
while (iterator.hasNext()) {
value = "";
Map.Entry<String, String[]> entry = iterator.next();
String pname = (String) entry.getKey();
if (Objects.equals("token", pname)) {
continue;
}
Object objValue = entry.getValue();
if (null == objValue) {
value = "";
} else {
String[] values = (String[]) objValue;
for (String s : values) {
value = s + ",";
}
if (value.length() > 0) {
value = value.substring(0, value.length() - 1);
}
}
if ("rnd".equals(pname)) {
rnd = value;
}
if (SafeUtil.checkSafeSql(value)) {
log.info("请求失败,当前请求参数不安全!请求地址:\n" + requestUrl + "\n不安全参数" + pname + ":" + value);
return false;
}
if (SafeUtil.checkSpecial(value) || SafeUtil.checkScript(value)) {
log.info("请求失败,当前请求参数包含特殊字符!请求地址:\n" + requestUrl + "\n特殊字符参数" + pname + ":" + value);
return false;
}
}
}
return true;
}
/**
* 通过rnd随机参数判断相同url是否多次请求访问
*
* @param currentRequest
* @param requestWrapper
* @return
*/
private boolean checkSameUrl(String currentRequest, XssRequestWrapper requestWrapper) {
if (rnd != null && rnd.length() > 0) {
try {
double newRnd = Double.parseDouble(rnd);
/**
* 当为空时新增请求时间记录第一次请求放行允许查询
*/
HttpSession session = requestWrapper.getSession();
Object obj = session.getAttribute("requestLogMap");
if (obj == null) {
requestLogMap = new HashMap<String, List<Double>>(100);
} else {
requestLogMap = (Map<String, List<Double>>) obj;
}
List<Double> list = requestLogMap.get(currentRequest);
if (list == null) {
list = new ArrayList<Double>();
} else {
for (Double oldRnd : list) {
if (oldRnd == newRnd) {
log.info("请求失败,当前请求已过期!请重新登录!您的请求地址:\n" + currentRequest);
return false;
}
}
}
list.add(newRnd);
requestLogMap.put(currentRequest, list);
String brute = "requestLogMap";
if (session.getAttribute(brute) != null) {
session.removeAttribute(brute);
}
session.setAttribute(brute, requestLogMap);
} catch (NumberFormatException e) {
log.info("rnd参数格式化错误 请检查");
return false;
}
} else {
log.info("请求失败,rnd参数不存在!请重新登录!您的请求地址:\n" + currentRequest);
return true;
}
return true;
}
/**
* 检查所有页面输入的参数是否安全 request.getReader()
*
* @param readerParam
* @param requestUrl
*/
private boolean checkReader(String readerParam, String requestUrl) {
if (SafeUtil.checkScript(readerParam) || SafeUtil.checkSafeSql(readerParam)) {
log.info("请求失败,当前请求参数不安全!请求地址:\n" + requestUrl + "\n不安全参数数据流:" + readerParam);
return false;
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// SecurityContextHolder.remove();
}
}

View File

@ -25,35 +25,42 @@ import java.util.regex.Pattern;
public class XssRequestWrapper extends HttpServletRequestWrapper {
private byte[] body;
private String queryString;
private String streamParam;
private boolean checked;
public XssRequestWrapper(HttpServletRequest request) {
super(request);
getParameterMap();
BufferedReader reader;
// 先读取请求体数据
try {
reader = request.getReader();
StringBuilder sb = new StringBuilder();
char[] buf = new char[1024];
int rd;
while ((rd = reader.read(buf)) != -1) {
sb.append(buf, 0, rd);
// 读取请求体内容
StringBuilder stringBuilder = new StringBuilder();
BufferedReader reader = request.getReader();
char[] charBuffer = new char[1024];
int bytesRead;
while ((bytesRead = reader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
reader.close();
streamParam = xssClean(sb.toString());
setChecked(xssCleanNew(sb.toString()) && xssCleanNew(request.getQueryString()));
body = streamParam.getBytes();
String requestBody = stringBuilder.toString();
// 进行XSS清理
streamParam = xssClean(requestBody);
body = streamParam.getBytes(request.getCharacterEncoding() != null ?
request.getCharacterEncoding() : "UTF-8");
// 检查安全性
String queryStr = request.getQueryString();
setChecked(xssCleanNew(requestBody) && (queryStr == null || xssCleanNew(queryStr)));
} catch (IOException e) {
log.error(e.getLocalizedMessage(),e);
log.error("读取请求体数据失败: {}", e.getLocalizedMessage(), e);
body = new byte[0];
streamParam = "";
setChecked(false);
}
queryString = xssClean(request.getQueryString());
}
@Override
@ -63,135 +70,132 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
return new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
return bais.available() == 0;
}
@Override
public boolean isReady() {
return false;
return true;
}
@Override
public void setReadListener(ReadListener listener) {
// 不需要实现
}
@Override
public int read() throws IOException {
int read = bais.read();
bais.close();
return read;
return bais.read();
}
};
}
@Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> requestMap = super.getParameterMap();
if(requestMap!=null){
Iterator iterator = requestMap.entrySet().iterator();
if (requestMap != null) {
Iterator<Map.Entry<String, String[]>> iterator = requestMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry me = (Map.Entry) iterator.next();
String[] values = (String[]) me.getValue();
Map.Entry<String, String[]> entry = iterator.next();
String[] values = entry.getValue();
for (int i = 0; i < values.length; i++) {
if (values[i] != null) {
values[i] = xssClean(values[i]);
}
}
}}
}
}
return requestMap;
}
@Override
public String[] getParameterValues(String paramString) {
String[] arrayOfString1 = super.getParameterValues(paramString);
if (arrayOfString1 == null){
String[] values = super.getParameterValues(paramString);
if (values == null) {
return null;
}
int i = arrayOfString1.length;
String[] arrayOfString2 = new String[i];
for (int j = 0; j < i; j++) {
if (arrayOfString1[j] != null) {
arrayOfString2[j] = xssClean(arrayOfString1[j]);
String[] cleanedValues = new String[values.length];
for (int i = 0; i < values.length; i++) {
if (values[i] != null) {
cleanedValues[i] = xssClean(values[i]);
}
}
return arrayOfString2;
return cleanedValues;
}
@Override
public String getParameter(String paramString) {
String str = super.getParameter(paramString);
if (str == null){
String value = super.getParameter(paramString);
if (value == null) {
return null;
}
return xssClean(str);
return xssClean(value);
}
@Override
public String getHeader(String paramString) {
String str = super.getHeader(paramString);
if (str == null){
String value = super.getHeader(paramString);
if (value == null) {
return null;
}
return xssClean(str);
return xssClean(value);
}
String regex1="<script>(.*?)</script>";
String regex2="src[\r\n]*=[\r\n]*'(.*?)'";
String regex3="src[\r\n]*=[\r\n]*\"(.*?)\"";
String regex4="</script>";
String regex5="<script(.*?)>";
String regex6="eval\\((.*?)\\)";
String regex7="e-xpression\\((.*?)\\)";
String regex8="javascript:";
String regex9="vbscript:";
String regex10="onload(.*?)=";
// 正则表达式模式
private static final String regex1 = "<script>(.*?)</script>";
private static final String regex2 = "src[\r\n]*=[\r\n]*'(.*?)'";
private static final String regex3 = "src[\r\n]*=[\r\n]*\"(.*?)\"";
private static final String regex4 = "</script>";
private static final String regex5 = "<script(.*?)>";
private static final String regex6 = "eval\\((.*?)\\)";
private static final String regex7 = "e-xpression\\((.*?)\\)";
private static final String regex8 = "javascript:";
private static final String regex9 = "vbscript:";
private static final String regex10 = "onload(.*?)=";
// 添加安全脚本模式
public static final String SAFE_SCRIPT_PATTERN = "(\\||;|\\$|'|\\'|0x0d|0x0a|\\%27|\\%3B|<>|\\[\\]|\\(\\)|/|\"|script|alert|svg|confirm|prompt|onload|%3c|%3e|%2b|@|!|img|src)";
private String xssClean(String value) {
if (value == null) {
return value;
return null;
}
value = value.replaceAll("", "");
Pattern scriptPattern = Pattern.compile(regex1, Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile(regex2, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile(regex3, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile(regex4, Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile(regex5, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile(regex6, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile(regex7, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile(regex8, Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile(regex9, Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile(regex10, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 移除空字符串替换这行代码没有实际效果
// value = value.replaceAll("", "");
// 使用预编译的模式提高性能
value = Pattern.compile(regex1, Pattern.CASE_INSENSITIVE).matcher(value).replaceAll("");
value = Pattern.compile(regex2, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL).matcher(value).replaceAll("");
value = Pattern.compile(regex3, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL).matcher(value).replaceAll("");
value = Pattern.compile(regex4, Pattern.CASE_INSENSITIVE).matcher(value).replaceAll("");
value = Pattern.compile(regex5, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL).matcher(value).replaceAll("");
value = Pattern.compile(regex6, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL).matcher(value).replaceAll("");
value = Pattern.compile(regex7, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL).matcher(value).replaceAll("");
value = Pattern.compile(regex8, Pattern.CASE_INSENSITIVE).matcher(value).replaceAll("");
value = Pattern.compile(regex9, Pattern.CASE_INSENSITIVE).matcher(value).replaceAll("");
value = Pattern.compile(regex10, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL).matcher(value).replaceAll("");
// 添加额外的安全过滤
value = Pattern.compile(SAFE_SCRIPT_PATTERN, Pattern.CASE_INSENSITIVE).matcher(value).replaceAll("");
return value;
}
private boolean xssCleanNew(String value) {
boolean find = false;
if (value == null) {
return true;
}
List<Pattern> patterns = new ArrayList<Pattern>();
List<Pattern> patterns = new ArrayList<>();
patterns.add(Pattern.compile(regex1, Pattern.CASE_INSENSITIVE));
patterns.add(Pattern.compile(regex2, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
patterns.add(Pattern.compile(regex3, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
@ -202,29 +206,21 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
patterns.add(Pattern.compile(regex8, Pattern.CASE_INSENSITIVE));
patterns.add(Pattern.compile(regex9, Pattern.CASE_INSENSITIVE));
patterns.add(Pattern.compile(regex10, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL));
patterns.add(Pattern.compile(SAFE_SCRIPT_PATTERN, Pattern.CASE_INSENSITIVE));
for (Pattern pattern : patterns) {
find = match(pattern, value) ;
if (find) {
break;
if (match(pattern, value)) {
return false; // 发现XSS攻击
}
}
return !find;
return true; // 安全
}
/**
* 执行正则表达式
*
* @param pattern
* 表达式
* @param str
* 待验证字符串
* @return 返回 <b>true </b>,否则为 <b>false </b>
* 执行正则表达式匹配
*/
private static boolean match(Pattern pattern, String str) {
Matcher m = pattern.matcher(str);
return m.find();
return pattern.matcher(str).find();
}
public String getReaderParam() {
@ -238,4 +234,11 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
public void setChecked(boolean checked) {
this.checked = checked;
}
}
// 添加字符编码支持
public String getCharacterEncoding() {
String encoding = super.getCharacterEncoding();
return encoding != null ? encoding : "UTF-8";
}
}