XSS跨站指令碼攻擊(三)-- 結合Spring MVC框架
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;
3.XssHttpServletRequestWrapper.javaimport 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; } }
某些情況下,我們不能對使用者資料進行嚴格的過濾,那我們也需要對標籤進行轉換。
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. |
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()方法。