1.web.xml中
<filter>
<filter-name>xssFilter</filter-name>
<filter-class>com.xxx.web.filter.XSSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>xssFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.XSSFilter.java
package com.xxx.web.filter;
import java.io.IOException;
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.HttpServletRequest;
import org.apache.commons.lang.StringEscapeUtils;
public class XssFilter implements Filter {
FilterConfig filterConfig;
public void init(FilterConfig config) throws ServletException {
this.filterConfig = filterConfig;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}
public void destroy() {
this.filterConfig = null;
}
}
3. XssHttpServletRequestWrapper.java
某些情况下,我们不能对用户数据进行严格的过滤,那我们也需要对标签进行转换。
less-than character (<) | < |
greater-than character (>) | > |
ampersand character (&) | & |
double-quote character (") | " |
space character( ) | |
Any ASCII code character whose code is greater-than or equal to 0x80 | &#<number>, where <number> is the ASCII character value. |
比如用户输入:<script>window.location.href=”http://www.baidu.com”;</script>,保存后最终存储的会是:<script>window.location.href="http://www.baidu.com"</script>在展现时浏览器会对这些字符转换成文本内容显示,而不是一段可执行的代码。
package com.xxx.web.filter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String[] getParameterValues(String parameter) {
String[] values = super.getParameterValues(parameter);
if (values == null) {
return null;
}
int count = values.length;
String[] encodedValues = new String[count];
for(int i=0;i<count;i++){
//encodedValues[i] = StringEscapeUtils.escapeHtml(values[i]);
encodedValues[i] = this.escapeHtml(values[i]);
}
return encodedValues;
}
@Override
public String getParameter(String parameter) {
String value = super.getParameter(parameter);
if (value == null) {
return null;
}
//return StringEscapeUtils.escapeHtml(value);
return this.escapeHtml(value);
}
/**
* 重写StringEscapeUtils.escapeHtml()方法,避免过滤中文
*
* @param s
* @return
*/
private String escapeHtml(String s) {
if (s == null || s.isEmpty()) {
return "";
}
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '>':
sb.append('>');
break;
case '<':
sb.append('<');
break;
case '"':
sb.append('"');
break;
case '&':
sb.append('&');
break;
case 10:
case 13:
break;
default:
sb.append(c);
break;
}
}
return sb.toString();
}
}
4.针对上面重写StringEscapeUtils.escapeHtml()方法,主要是,从前端传入后台的数据,如果是中文的话,使用StringEscapeUtils.escapeHtml(value)就会把中文也转码了,这样不是我们希望看到的。,因此需要重写方法。
5.如果我们前端传的参数是一个json串,那么到了后端需要对双引号特殊处理,比如:
前端:
var arrChoosed = [{"id":parseInt('10'),"name":"詹三"},{.....}];
ajax传入后端参数为data:{'params':JSON.stringify(arrChoosed),.....}
后端:
String parameter = request.getParameter("params").replaceAll(""","\"");
ObjectMapper mapper = new ObjectMapper();
List<Map<String,Object>> paramList = mapper.readValue(parameter,List.class);
6.针对Spring MVC中的@RequestParam获取的参数,走的是3中的getParameterValues()方法。