struts2如何防止XSS脚本攻击(XSS防跨站脚本攻击过滤器)

只需要配置一个拦截器即可解决参数内容替换

一、配置web.xml

java 复制代码
<filter>
		<filter-name>struts-xssFilter</filter-name>
		<filter-class>*.*.filters.XssFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>struts-xssFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

二、编写XssFilter

java 复制代码
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class XssFilter implements Filter{

    FilterConfig filterConfig = null;
    /**
     * Default constructor.
     */
    public XssFilter() {
    }

    public void destroy() {
        this.filterConfig = null;
    }

    public void init(FilterConfig fConfig) throws ServletException {
        this.filterConfig = fConfig;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        String url = req.getRequestURI();
        //过滤不需要拦截的action
        if(url.indexOf("*.action") != -1){
            chain.doFilter(request, response);
        }else{
            chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);
        }
    }
}

三、XssHttpServletRequestWrapper 实现 StrutsRequestWrapper完成参数替换

java 复制代码
import cn.hutool.http.HtmlUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.dispatcher.StrutsRequestWrapper;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Map;
import java.util.regex.Pattern;
public class XssHttpServletRequestWrapper extends StrutsRequestWrapper {

    HttpServletRequest orgRequest = null;

    public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
        super(servletRequest);
        orgRequest = servletRequest;
    }
    /**
     * 重写getParameterValues方法
     * 通过循环取出每一个请求结果
     * 再对请求结果进行过滤
     * */
    public String[] getParameterValues(String parameter) {
        String[] values = super.getParameterValues(parameter);
        if (values == null) {
            return null;
        }
        int count = values.length;
        String[] encodedValues = new String[count];
        for (int i = 0; i < count; i++) {
            encodedValues[i] = cleanXSS(values[i]);
        }
        return encodedValues;
    }

    /**
     * 重写getParameter方法
     * 对请求结果进行过滤
     * */
    public String getParameter(String parameter) {
        String value = super.getParameter(parameter);
        if (value == null) {
            return null;
        }
        return cleanXSS(value);
    }

    public String getHeader(String name) {
        String value = super.getHeader(name);
        if (value == null)
            return null;
        return cleanXSS(value);
    }
    /**
     * 获取最原始的request
     *
     * @return
     */
    public HttpServletRequest getOrgRequest() {
        return orgRequest;
    }

    /**
     * 获取最原始的request的静态方法
     *
     * @return
     */
    public static HttpServletRequest getOrgRequest(HttpServletRequest req) {
        if (req instanceof XssHttpServletRequestWrapper) {
            return ((XssHttpServletRequestWrapper) req).getOrgRequest();
        }
        return req;
    }

    @Override
    public Enumeration<String> getParameterNames() {
        Enumeration<String> names = super.getParameterNames();
        while(names.hasMoreElements()){
            String name = names.nextElement();
            name = cleanXSS(name);
        }
        return names;
    }


    @Override
    public Map getParameterMap() {
        Map paramMap = super.getParameterMap();
        if (CollectionUtils.isEmpty(paramMap)) {
            return paramMap;
        }

        for (Object value : paramMap.values()) {
            String[] str = (String[])value;
            if (str != null) {
                for (int i = 0; i < str.length; i++) {
                    str[i] = cleanXSS(str[i]);
                }
            }
        }
        return paramMap;
    }

    private String cleanXSS(String value) {
        if (StringUtils.isNotBlank(value)) {
            // 推荐使用ESAPI库来避免脚本攻击,
            value = HtmlUtil.filter(value);
            // 避免空字符串
            value = value.replaceAll(" ", "");
            // 避免script 标签
            Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // 避免src形式的表达式
            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // 删除单个的 </script> 标签
            scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // 删除单个的<script ...> 标签
            scriptPattern = Pattern.compile("<script(.*?)>",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // 避免 eval(...) 形式表达式
            scriptPattern = Pattern.compile("eval\\((.*?)\\)",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // 避免 expression(...) 表达式
            scriptPattern = Pattern.compile("expression\\((.*?)\\)",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // 避免 javascript: 表达式
            scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // 避免 vbscript:表达式
            scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // 避免 onload= 表达式
            scriptPattern = Pattern.compile("onload(.*?)=",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
        }
        return value;
    }

四、pom需要引入hutool

java 复制代码
<dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.6.0</version>
        </dependency>

五、测试结果通过

相关推荐
君顾113 分钟前
代驾跑腿业务系统实战开发指南
java·开发语言·代驾跑腿
NGINX开源社区1 小时前
NGINX Ingress Controller 5.5:安全性与性能提升,迁移更轻松
java·服务器·nginx
云烟成雨TD1 小时前
Micrometer 系列【25】Spring Boot Actuator | Spring MVC、Spring WebFlux 指标
java·spring boot·micrometer
liudashuang20171 小时前
Kafka Producer 隐藏深坑:Sender 线程自阻塞(自死锁)导致 BufferExhaustedException 完整复盘
java·分布式·kafka·linq
风筱1 小时前
Idea的CC GUI插件安装Claude Code SDK失败
java·ide·ai编程
m0_527034331 小时前
异步任务审核系统设计:消息队列、超时重试与失败补偿
java·大数据·开发语言
xbgRS2 小时前
springBoot项目配置加载优先级
java·spring boot
zzzll11112 小时前
Loop Engineering:循环工程的原理、实践与应用
java·数据库·python
假客套2 小时前
记一次若依 Excel 导出踩坑:Permission denied、401 报错完整排查记录
java·若依·linux服务器
岁岁养乐多2 小时前
深入解析 Spring @Cacheable 注解:从声明式缓存 到多维替代方案
java