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>

五、测试结果通过

相关推荐
264玫瑰资源库1 小时前
问道数码兽 怀旧剧情回合手游源码搭建教程(反查重优化版)
java·开发语言·前端·游戏
pwzs1 小时前
Java 中 String 转 Integer 的方法与底层原理详解
java·后端·基础
东阳马生架构1 小时前
Nacos简介—2.Nacos的原理简介
java
普if加的帕1 小时前
java Springboot使用扣子Coze实现实时音频对话智能客服
java·开发语言·人工智能·spring boot·实时音视频·智能客服
爱喝一杯白开水1 小时前
SpringMVC从入门到上手-全面讲解SpringMVC的使用.
java·spring·springmvc
王景程2 小时前
如何测试短信接口
java·服务器·前端
小杨升级打怪中2 小时前
前端面经-JS篇(三)--事件、性能优化、防抖与节流
前端·javascript·xss
zhang23839061543 小时前
IDEA add gitlab account 提示
java·gitlab·intellij-idea·idea
牛马baby3 小时前
Java高频面试之并发编程-07
java·开发语言·面试
卓怡学长3 小时前
w304基于HTML5的民谣网站的设计与实现
java·前端·数据库·spring boot·spring·html5