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>

五、测试结果通过

相关推荐
跃ZHD9 分钟前
BolckingQueue
java
西岭千秋雪_16 分钟前
谷粒商城のElasticsearch
java·大数据·服务器·spring boot·elasticsearch·搜索引擎
yueqingll44 分钟前
020、二级Java选择题综合知识点(持续更新版)
java·开发语言
许野平1 小时前
Rust:深入浅出说一说 Error 类型
java·开发语言·rust·error
jingling5551 小时前
后端开发刷题 | 数字字符串转化成IP地址
java·开发语言·javascript·算法
茜茜西西CeCe2 小时前
大数据处理技术:HBase的安装与基本操作
java·大数据·数据库·hbase·头歌·大数据处理技术
ZachOn1y2 小时前
Java 入门指南:JVM(Java虚拟机)垃圾回收机制 —— 死亡对象判断方法
java·jvm·后端·java-ee·团队开发·个人开发
J老熊2 小时前
Linux下抓包分析Java应用程序HTTP接口调用:基于tcpdump与Wireshark的综合示例
java·linux·运维·web安全·http·面试
ZachOn1y2 小时前
Java 入门指南:JVM(Java虚拟机)垃圾回收机制 —— 内存分配和回收规则
java·jvm·后端·个人开发
jingling5552 小时前
后端开发刷题 | 最长上升子序列
java·开发语言·数据结构·后端·算法·动态规划