XSS攻击防御的filter实现

来源:互联网 发布:阿里标题优化工具 编辑:程序博客网 时间:2024/05/17 00:10

XSS攻击的基本概念主要是:
    恶意用户在网页的可输入的地方输入可执行的脚本(如javascript)代码,从而使网页解析执行该脚本代码来达到攻击的效果, 比如在网站上写一篇文章时包含这段代码: ,如果该字符串在后台没有进行XSS攻击防范,就会导致导致其他人访问该文章时网页执行上面的脚本从而alert(1).

防止XSS攻击最主要方式 :
      把特殊标签符号转码,比如把”<”, “>”, “&”等这些特殊字符转码即可防止XSS攻击.

要考虑代码的维护问题,我们不能把太多的XSS防攻击代码侵入到业务代码中, 我们可以使用过滤器的方式来转换编码.在过滤器中获取每一个参数进行转换编码:

做法:
1. 在web.xml中加入filter如下:

    <!--配置XSS防攻击的过滤器-->    <filter>        <filter-name>XSSFilter</filter-name>        <filter-class>com.xxx.xxx.filter.XSSFilter</filter-class>    </filter>    <filter-mapping>        <filter-name>XSSFilter</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping>

编写filter实现如下:
(默认情况下request只有getParameter()方法而没有setParameter方法, 所以默认情况下我们无法将转码后的参数放回request中的, 所以我们需要自己实现一个包装类来处理参数)

package com.xxx.xxx.filter;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import java.io.IOException;/** * 防止XSS攻击的过滤器类 * @Author yss * @Version 1.0 * @see */public class XSSFilter implements Filter {    @Override    public void init(FilterConfig filterConfig) throws ServletException {    }    /**     * @param request 请求     * @param servletResponse 相应     * @param filterChain 过滤器链     * @throws IOException 异常     * @throws ServletException 异常     */    @Override    public void doFilter(ServletRequest request, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {//自定义request包装类,并把它传入过滤器链        ParameterRequestWrapper requestWrapper = new ParameterRequestWrapper((HttpServletRequest) request);        filterChain.doFilter(requestWrapper, servletResponse);    }    @Override    public void destroy() {    }}
package com.xxx.xxx.filter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import java.util.HashMap;import java.util.Map;/** * request的参数包装类 * @Author yss * @Version 1.0 * @see */public class ParameterRequestWrapper extends HttpServletRequestWrapper {    private Map<String , String[]> params = new HashMap<String, String[]>();    @SuppressWarnings("unchecked")    public ParameterRequestWrapper(HttpServletRequest request) {        // 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似        super(request);        //将参数表,赋予给当前的Map以便于持有request中的参数        this.params.putAll(request.getParameterMap());    }    /**     * 重写getParameter,代表参数从当前类中的map获取     * @param name     * @return     */    @Override    public String getParameter(String name) {        String[]values = params.get(name);        if(values == null || values.length == 0) {            return null;        }        String result = values[0];        result = htmlEncode(result);//转码        return result;    }    public String[] getParameterValues(String name) {//同上        if(params.get(name) instanceof String[]) {//数组            int size = ((String[])params.get(name)).length;            String[] vals = new String[size];            for(int i=0;i<((String[])params.get(name)).length;i++) {                String str = htmlEncode(((String[])params.get(name))[i]);//转码                vals[i] = str;            }            return  vals;        }         return null;    }   public void addAllParameters(Map<String , Object>otherParams) {//增加多个参数        for(Map.Entry<String , Object>entry : otherParams.entrySet()) {            addParameter(entry.getKey() , entry.getValue());        }    }    public void addParameter(String name , Object value) {//增加参数        if(value != null) {            if(value instanceof String[]) {                params.put(name , (String[])value);            }else if(value instanceof String) {                params.put(name , new String[] {(String)value});            }else {                params.put(name , new String[] {String.valueOf(value)});            }        }    }    /**     * 对传入的字符串str进行Html encode转换     * @param value 需要处理的字符串     * @return 处理后的字符串     */    public static String htmlEncode(String value) {        StringBuffer stringBuffer = new StringBuffer();        for (int i = 0, len = value.length(); i < len; i++) {            stringBuffer.append(htmlEncode(value.charAt(i)));        }        return stringBuffer.toString();    }    /**转码规则:     * 对每一个字符进行检查,转换字符。     * @param c     * @return     */    private static String htmlEncode(char c) {        switch (c) {            case '&':                return "&amp;";            case '<':                return "&lt;";            case '>':                return "&gt;";            case '"':                return "&quot;";            case ' ':                return "&nbsp;";            default:                return c + "";        }    }}

但有一个问题没解决,就是如果提交一个包含文件属性的表单时, 这个filter没法拦截, 测试了几次没找到好的方法, 网上也没有找到关于这方面的解决方案, (自己遇到这种情况时是在业务逻辑中侵入了少量的过滤代码) . 如果各位大大找到包含文件的表单的过滤器实现方案,欢迎留言.

1 0
原创粉丝点击