Struts2 Xss 攻击预防的处理

简介: 关于XSS问题的处理,此前在博客 http://blog.csdn.net/catoop/article/details/50338259 中写过处理方法。刚好最近朋友有问到“在Struts2中按文章中那样处理无效”,后来验证了下发现,Struts2 对请求的二次封装有所不同,于是针对Struts.

关于XSS问题的处理,此前在博客 http://blog.csdn.net/catoop/article/details/50338259 中写过处理方法。刚好最近朋友有问到“在Struts2中按文章中那样处理无效”,后来验证了下发现,Struts2 对请求的二次封装有所不同,于是针对Struts2如何处理XSS问题,按照本文的方法可以解决。

其主要思路就是,重写了StrutsPrepareAndExecuteFilter过滤器。

正常情况下我们在web.xml 中配置StrutsPrepareAndExecuteFilter的代码为:

…………
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
…………

将文章后面的几个类保存到项目中后,修改web.xml 的配置,指定我们新的MStrutsPrepareAndExecuteFilter类,代码如下:

…………
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>cn.gx.wedding.common.struts2.MStrutsPrepareAndExecuteFilter</filter-class>
    </filter>
…………

下面是相关的4个类源码(直接下载附件也行)
MDispatcher.java
MMultiPartRequestWrapper.java
MStrutsPrepareAndExecuteFilter.java
MStrutsRequestWrapper.java

这里说明下,因为struts2的源码中这4个类存在紧密的依赖耦合,所以只能把这4个类都重写出来,实际上其中并没有修改什么(详见MMultiPartRequestWrapper.java 和 MStrutsRequestWrapper.java)。

package cn.gx.wedding.common.struts2;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.dispatcher.StrutsRequestWrapper;

import cn.gx.wedding.util.XssShieldUtil;

public class MStrutsRequestWrapper extends StrutsRequestWrapper {

    public MStrutsRequestWrapper(HttpServletRequest req) {
        super(req);
    }
    
    public MStrutsRequestWrapper(HttpServletRequest req, boolean bool) {
        super(req, bool);
    }

    @Override
    public String getParameter(String name) {
        name = XssShieldUtil.stripXss(name);
        // 返回值之前 先进行过滤
        return XssShieldUtil.stripXss(super.getParameter(name));
    }

    @Override
    public String[] getParameterValues(String name) {
        name = XssShieldUtil.stripXss(name);
        // 返回值之前 先进行过滤
        String[] values = super.getParameterValues(name);
        if(values != null){
            for (int i = 0; i < values.length; i++) {
                values[i] = XssShieldUtil.stripXss(values[i]);
            }
        }
        return values;
    }

    @Override
    public Enumeration<String> getParameterNames() {
//        Enumeration<String> names = super.getParameterNames();
//        while(names.hasMoreElements()){
//            String name = names.nextElement();
//            name = XssShieldUtil.stripXss(name);
//        }
//        return names;
        
        return super.getParameterNames();
    }
    
}
package cn.gx.wedding.common.struts2;

import java.io.File;
import java.io.IOException;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.StrutsConstants;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.StrutsRequestWrapper;
import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;

import com.opensymphony.xwork2.LocaleProvider;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;

public class MDispatcher extends Dispatcher {

    /**
     * Provide a logging instance.
     */
    private static final Logger LOG = LoggerFactory.getLogger(MDispatcher.class);
    
    /**
     * Store state of StrutsConstants.DISABLE_REQUEST_ATTRIBUTE_VALUE_STACK_LOOKUP setting.
     */
    private boolean disableRequestAttributeValueStackLookup;
    
    private ServletContext servletContext;
    private Map<String, String> initParams;

    private String multipartSaveDir;
    
    /**
     * Store state of StrutsConstants.STRUTS_DEVMODE setting.
     */
    private boolean devMode;
    
    public MDispatcher(ServletContext servletContext, Map<String, String> initParams) {
        super(servletContext, initParams);
        this.servletContext = servletContext;
        this.initParams = initParams;
    }
    
    @Override
    public HttpServletRequest wrapRequest(HttpServletRequest request, ServletContext servletContext)
            throws IOException {
         // don't wrap more than once
        if (request instanceof StrutsRequestWrapper) {
            return request;
        }

        String content_type = request.getContentType();
        if (content_type != null && content_type.contains("multipart/form-data")) {
            MultiPartRequest mpr = getMultiPartRequest();
            LocaleProvider provider = getContainer().getInstance(LocaleProvider.class);
            request = new MMultiPartRequestWrapper(mpr, request, getSaveDir(servletContext), provider);
        } else {
            request = new MStrutsRequestWrapper(request, disableRequestAttributeValueStackLookup);
        }

        return request;
    }

    private String getSaveDir(ServletContext servletContext) {
        String saveDir = multipartSaveDir.trim();

        if (saveDir.equals("")) {
            File tempdir = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
            if (LOG.isInfoEnabled()) {
            LOG.info("Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir");
            }

            if (tempdir != null) {
                saveDir = tempdir.toString();
                setMultipartSaveDir(saveDir);
            }
        } else {
            File multipartSaveDir = new File(saveDir);

            if (!multipartSaveDir.exists()) {
                if (!multipartSaveDir.mkdirs()) {
                    String logMessage;
                    try {
                        logMessage = "Could not find create multipart save directory '" + multipartSaveDir.getCanonicalPath() + "'.";
                    } catch (IOException e) {
                        logMessage = "Could not find create multipart save directory '" + multipartSaveDir.toString() + "'.";
                    }
                    if (devMode) {
                        LOG.error(logMessage);
                    } else {
                        if (LOG.isWarnEnabled()) {
                            LOG.warn(logMessage);
                        }
                    }
                }
            }
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("saveDir=" + saveDir);
        }

        return saveDir;
    }
    
    /**
     * Modify state of StrutsConstants.STRUTS_MULTIPART_SAVEDIR setting.
     * @param val New setting
     */
    @Override
    @Inject(StrutsConstants.STRUTS_MULTIPART_SAVEDIR)
    public void setMultipartSaveDir(String val) {
        multipartSaveDir = val;
    }
    
    /**
     * Modify state of StrutsConstants.STRUTS_DEVMODE setting.
     * @param mode New setting
     */
    @Override
    @Inject(StrutsConstants.STRUTS_DEVMODE)
    public void setDevMode(String mode) {
        devMode = "true".equals(mode);
    }
}
package cn.gx.wedding.common.struts2;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;

import cn.gx.wedding.util.XssShieldUtil;

import com.opensymphony.xwork2.LocaleProvider;

public class MMultiPartRequestWrapper extends MultiPartRequestWrapper {

    public MMultiPartRequestWrapper(MultiPartRequest multiPartRequest, HttpServletRequest request, String saveDir,
            LocaleProvider provider) {
        super(multiPartRequest, request, saveDir, provider);
    }

    @Override
    public String getParameter(String name) {
        name = XssShieldUtil.stripXss(name);
        // 返回值之前 先进行过滤
        return XssShieldUtil.stripXss(super.getParameter(name));
    }

    @Override
    public String[] getParameterValues(String name) {
        name = XssShieldUtil.stripXss(name);
        // 返回值之前 先进行过滤
        String[] values = super.getParameterValues(name);
        if(values != null){
            for (int i = 0; i < values.length; i++) {
                values[i] = XssShieldUtil.stripXss(values[i]);
            }
        }
        return values;
    }

    @Override
    public Enumeration<String> getParameterNames() {
//        Enumeration<String> names = super.getParameterNames();
//        while(names.hasMoreElements()){
//            String name = names.nextElement();
//            name = XssShieldUtil.stripXss(name);
//        }
//        return names;
        
        return super.getParameterNames();
    }
    
}
package cn.gx.wedding.common.struts2;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.FilterConfig;
import javax.servlet.ServletException;

import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.ng.ExecuteOperations;
import org.apache.struts2.dispatcher.ng.HostConfig;
import org.apache.struts2.dispatcher.ng.InitOperations;
import org.apache.struts2.dispatcher.ng.PrepareOperations;
import org.apache.struts2.dispatcher.ng.filter.FilterHostConfig;
import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;

public class MStrutsPrepareAndExecuteFilter extends StrutsPrepareAndExecuteFilter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        InitOperations init = new InitOperations();
        Dispatcher dispatcher = null;
        try {
            FilterHostConfig config = new FilterHostConfig(filterConfig);
            init.initLogging(config);
            dispatcher = initDispatcher(config);
            init.initStaticContentLoader(config, dispatcher);

            prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
            execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
            this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);

            postInit(dispatcher, filterConfig);
        } finally {
            if (dispatcher != null) {
                dispatcher.cleanUpAfterInit();
            }
            init.cleanup();
        }
    }

    /**
     * Creates and initializes the dispatcher
     */
    public Dispatcher initDispatcher(HostConfig filterConfig) {
        Dispatcher dispatcher = createDispatcher(filterConfig);
        dispatcher.init();
        return dispatcher;
    }

    /**
     * Create a {@link Dispatcher}
     */
    private Dispatcher createDispatcher(HostConfig filterConfig) {
        Map<String, String> params = new HashMap<String, String>();
        for (Iterator e = filterConfig.getInitParameterNames(); e.hasNext();) {
            String name = (String) e.next();
            String value = filterConfig.getInitParameter(name);
            params.put(name, value);
        }
        return new MDispatcher(filterConfig.getServletContext(), params);
    }
}

如果使用的是springmvc、springboot等其他“非struts2”的框架,请参考 http://blog.csdn.net/catoop/article/details/50338259

目录
相关文章
|
1月前
|
JavaScript 安全 前端开发
同源策略如何防止 XSS 攻击?
【10月更文挑战第31天】同源策略通过对 DOM 访问、Cookie 访问、脚本执行环境和跨源网络请求等多方面的严格限制,构建了一道坚实的安全防线,有效地防止了 XSS 攻击,保护了用户在网络浏览过程中的数据安全和隐私。
99 49
|
5月前
|
存储 安全 JavaScript
手摸手带你进行XSS攻击与防御
当谈到网络安全和信息安全时,跨站脚本攻击(XSS)是一个不可忽视的威胁。现在大家使用邮箱进行用户认证比较多,如果黑客利用XSS攻陷了用户的邮箱,拿到了cookie那么就可以冒充你进行收发邮件,那真就太可怕了,通过邮箱验证进行其他各种网站的登录与高危操作。 那么今天,本文将带大家深入了解XSS攻击与对应的防御措施。
|
1月前
|
安全 前端开发 Java
Web安全进阶:XSS与CSRF攻击防御策略深度解析
【10月更文挑战第26天】Web安全是现代软件开发的重要领域,本文深入探讨了XSS和CSRF两种常见攻击的原理及防御策略。针对XSS,介绍了输入验证与转义、使用CSP、WAF、HTTP-only Cookie和代码审查等方法。对于CSRF,提出了启用CSRF保护、设置CSRF Token、使用HTTPS、二次验证和用户教育等措施。通过这些策略,开发者可以构建更安全的Web应用。
87 4
|
1月前
|
安全 Go PHP
Web安全进阶:XSS与CSRF攻击防御策略深度解析
【10月更文挑战第27天】本文深入解析了Web安全中的XSS和CSRF攻击防御策略。针对XSS,介绍了输入验证与净化、内容安全策略(CSP)和HTTP头部安全配置;针对CSRF,提出了使用CSRF令牌、验证HTTP请求头、限制同源策略和双重提交Cookie等方法,帮助开发者有效保护网站和用户数据安全。
70 2
|
1月前
|
存储 安全 Go
Web安全基础:防范XSS与CSRF攻击的方法
【10月更文挑战第25天】Web安全是互联网应用开发中的重要环节。本文通过具体案例分析了跨站脚本攻击(XSS)和跨站请求伪造(CSRF)的原理及防范方法,包括服务器端数据过滤、使用Content Security Policy (CSP)、添加CSRF令牌等措施,帮助开发者构建更安全的Web应用。
92 3
|
1月前
|
SQL 存储 安全
什么是XSS攻击?什么是SQL注入攻击?什么是CSRF攻击?
理解并防范XSS、SQL注入和CSRF攻击是Web应用安全的基础。通过采用严格的输入验证、使用安全编码实践以及实现适当的身份验证和授权机制,可以有效防止这些常见的Web攻击,保障应用程序和用户的数据安全。
40 0
|
3月前
|
存储 前端开发 JavaScript
浅谈Web前端安全策略xss和csrf,及又该如何预防?
该文章详细讨论了Web前端安全中的XSS(跨站脚本攻击)和CSRF(跨站请求伪造)攻击原理及其防范措施,帮助读者了解如何保护Web应用程序免受这两种常见安全威胁的影响。
浅谈Web前端安全策略xss和csrf,及又该如何预防?
|
3月前
|
存储 安全 JavaScript
XSS跨站脚本攻击详解(包括攻击方式和防御方式)
这篇文章详细解释了XSS跨站脚本攻击的概念、原理、特点、类型,并提供了攻击方式和防御方法。
554 1
|
2月前
|
存储 JavaScript 安全
|
2月前
|
存储 JavaScript 前端开发
Xss跨站脚本攻击(Cross Site Script)
Xss跨站脚本攻击(Cross Site Script)