您的位置:首页 > 其它

XSS攻击防御的filter实现

2016-09-01 09:29 127 查看
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 "&";
case '<':
return "<";
case '>':
return ">";
case '"':
return """;
case ' ':
return " ";
default:
return c + "";
}
}
}


但有一个问题没解决,就是如果提交一个包含文件属性的表单时, 这个filter没法拦截, 测试了几次没找到好的方法, 网上也没有找到关于这方面的解决方案, (自己遇到这种情况时是在业务逻辑中侵入了少量的过滤代码) . 如果各位大大找到包含文件的表单的过滤器实现方案,欢迎留言.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息