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()方法。