解决XSS或CRSF等http注入攻击的问题

通过自定义请求头的方式,替换攻击头里面输入的特殊字符来解决

包装HttpServletRequest

自定义ProxyHttpServletRequest包装HttpServletRequest的请求,需要继HttpServletRequestWrapper类,重写getParameter和getParameterValues方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.heagle.web.filter;

import org.apache.commons.lang.StringUtils;

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

public class ProxyHttpServletRequest extends HttpServletRequestWrapper {

/**
* script 开始标签
*/
private static String script_start="<script>";

/**
* script 结束标签
*/
private static String script_end="</script>";

public ProxyHttpServletRequest(HttpServletRequest request) {
super(request);
}

/**
* 根据参数名获取数值
* @param name
* @return
*/
@Override
public String getParameter(String name) {
String targetValue=this.getRequest().getParameter(name);
if(StringUtils.isBlank(targetValue)){
return targetValue;
}
return scriptFilter(targetValue);
}

/**
* 根据参数名获取数组
* @param name
* @return
*/
@Override
public String[] getParameterValues(String name) {
String[]targetValues=this.getRequest().getParameterValues(name);
if(targetValues==null||targetValues.length==0){
return targetValues;
}
String []resultValues=targetValues;
for(int i=0;i<targetValues.length;i++){
String value=targetValues[i];
resultValues[i]= scriptFilter(value);
}
return resultValues;
}

private String scriptFilter(String source) {
return source.replace(script_start,"").replace(script_end,"");
}

}

包装MultipartHttpServletRequest

自定义ProxyDefaultMultipartHttpServletRequest来包装MultipartHttpServletRequest的请求,需要继承spring默认实现的DefaultMultipartHttpServletRequest请求,同样也是重写getParameter和getParameterValues方法来解决.注意自定义请求类,引用父类构造方法时要引用三参构造方法,不然父类的私有属性会没有初始化.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.heagle.web.filter;

import org.apache.commons.lang.StringUtils;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;

public class ProxyDefaultMultipartHttpServletRequest extends DefaultMultipartHttpServletRequest{

/**
* script 开始标签
*/
private static String script_start="<script>";

/**
* script 结束标签
*/
private static String script_end="</script>";

public ProxyDefaultMultipartHttpServletRequest(MultipartHttpServletRequest request) {
super(request,request.getFileMap(),request.getParameterMap());
}

public String getParameter(String name) {
String targetValue = "";
String[] values = (String[])((String[])this.getMultipartParameters().get(name));
if (values != null) {
targetValue = values.length > 0 ? values[0] : null;
} else {
targetValue = super.getParameter(name);
}
if(StringUtils.isNotBlank(targetValue)){
return scriptFilter(targetValue);
}else{
return null;
}

}

public String[] getParameterValues(String name) {
String[] targetValues = (String[])((String[])this.getMultipartParameters().get(name));
if(targetValues == null){
targetValues = super.getParameterValues(name);
}
if(targetValues == null || targetValues.length ==0){
return targetValues;
}
String []resultValues=targetValues;
for(int i=0;i<targetValues.length;i++){
String value=targetValues[i];
resultValues[i]= scriptFilter(value);
}
return resultValues;
}

private String scriptFilter(String source) {
return source.replace(script_start,"").replace(script_end,"");
}

}

doFilter方法说明

在自定义过滤器里面判断请求类型,然后根据请求类型创建不同的自定义请求对象,注意如果是MultipartRequest,需要在过滤器类里面先根据multipartResolver#resolveMultipart方法初始化创建MultipartHttpServletRequest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
public void doFilter(ServletRequest srequest, ServletResponse sresponse,
FilterChain chain) throws IOException, ServletException {
//Xss特殊字符过滤
String contentType = request.getContentType();
HttpServletRequest xssRequest = null;
if (contentType != null && contentType.toLowerCase().contains("multipart")) {
xssRequest = new ProxyDefaultMultipartHttpServletRequest(getRequest(request));
}else {
xssRequest = new ProxyHttpServletRequest(request);
}
chain.doFilter(xssRequest, response);
}

private MultipartHttpServletRequest getRequest(ServletRequest req){
String enctype = req.getContentType();
if (StringUtils.isNotBlank(enctype) && enctype.contains("multipart"))
// 返回 MultipartHttpServletRequest 用于获取 multipart/form-data 方式提交的请求中 上传的参数
return multipartResolver.resolveMultipart((HttpServletRequest) req);
else
return null;
}