防XSS攻击解决方法

1.web.xml文件中新增filter配置

<!-- URL请求参数字符过滤或合法性校验 -->
    <filter>
        <filter-name>XssFilter</filter-name>
        <filter-class>com.isoftstone.ifa.web.base.filter.XssFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>XssFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
filter

2.创建XssFilter实例

package com.isoftstone.ifa.web.base.filter;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class XssFilter implements Filter {
    FilterConfig filterConfig = null;
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    @Override
    public void doFilter(ServletRequest req,
            ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;    
        HttpServletResponse response = (HttpServletResponse) res;    
       
        chain.doFilter(new XssHttpServletRequestWrapper(request), response);        
    }

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

}
XssFilter

3.重写HttpServletRequestWrapper方法

package com.isoftstone.ifa.web.base.filter;

import java.util.Enumeration;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    private static final Logger logger = LoggerFactory.getLogger(XssHttpServletRequestWrapper.class);
    
    public XssHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    /**
     * 对数组参数进行特殊字符过滤
     */
    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);
        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;
    }

    /**
     * 对参数中特殊字符进行过滤
     */
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (value == null) {
            return null;
        }
        return cleanXSS(value);
    }
    
    /**
     * 对参数中特殊字符进行过滤(POST)
     */
    /*@SuppressWarnings("rawtypes")
    public Enumeration getParameterNames(){
        Enumeration params = super.getParameterNames();
        String paramValue = "";
        while (params.hasMoreElements()) {
            String param = (String) params.nextElement();
            String[] values = super.getParameterValues(param);
            for (int i = 0; i < values.length; i++) {
                paramValue = values[i];
                paramValue = cleanXSS(paramValue);
                values[i] = paramValue;
            }
            super.setAttribute(param, paramValue);
        }
        return params;
    }*/
    
    /**
     * 对请求头部进行特殊字符过滤
     
    @Override 
    public String getHeader(String name) { 
        String value = super.getHeader(name); 
        if (value == null) { 
            return null; 
        } 
        return cleanXSS(value); 
    }     
    */ 
    
    private String cleanXSS(String value) {
         logger.debug("过滤前传递参数:{}" , value);
         if (value != null) {
             /**
             //推荐使用ESAPI库来避免脚本攻击,value = ESAPI.encoder().canonicalize(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(""); 
             // 避免 e­xpression(...) 表达式 
             scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)", 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(""); 
             
            //移除特殊标签
            value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
        }
        logger.debug("过滤后传递参数:{}" , value);
        return value; 
     }
}
HttpServletRequestWrapper

 

posted @ 2019-01-18 15:15  超神之巅  阅读(1721)  评论(0编辑  收藏  举报