filter 防xss 对 request数据进行修改
这里采用了HttpServletRequestWrapper这个类,这个类是HttpServletRequest的包装类,对应的HttpServletResponseWrapper是HttpServletResponse的包装类。
首先,读取request里面的数据有三种形式
request.getParameter()
request.getInputStream()
request.getReader()
详情请查看 http://blog.csdn.net/clam_clam/article/details/6570539
如果可以通过getParameter()读取数据,那么可以用下面的方式进行xss的防御(request数据的修改)
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.util.regex.Pattern; public class XSSRequestWrapper1 extends HttpServletRequestWrapper { public XSSRequestWrapper1(HttpServletRequest servletRequest) { super(servletRequest); } @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] = stripXSS(values[i]); } return encodedValues; } @Override public String getParameter(String parameter) { String value = super.getParameter(parameter); return stripXSS(value); } @Override public String getHeader(String name) { String value = super.getHeader(name); return stripXSS(value); } private static String stripXSS(String value) { if (value != null) { // NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to // avoid encoded attacks. // value = ESAPI.encoder().canonicalize(value); // Avoid null characters value = value.replaceAll("", ""); // Avoid anything between script tags Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Avoid anything in a src="http://www.yihaomen.com/article/java/..." type of expression scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Remove any lonesome </script> tag scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Remove any lonesome <script ...> tag scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Avoid eval(...) expressions scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Avoid expression(...) expressions scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Avoid javascript:... expressions scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Avoid vbscript:... expressions scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Avoid onload= expressions scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); value = value.replaceAll("<", "<").replaceAll(">", ">"); } return value; } }
如果可以通过getReader()读取数据,那么可以用下面的方式进行xss的防御(request数据的修改)
public class XSSRequestWrapper extends HttpServletRequestWrapper { private static final Logger logger = LoggerFactory.getLogger(XSSRequestWrapper.class); /** * 用于保存读取body中数据 */ private final byte[] body; /** * 获取Body转换的JSON对象 * @param request * @return */ public static JSONObject getBodyJson(ServletRequest request) { JSONObject bodyJson; try { String bodyStr = getBodyStr(request); if(bodyStr!=null && bodyStr.replace(" ","").length()>0){ bodyJson = JSONObject.fromObject(bodyStr); }else{ bodyJson = new JSONObject(); } } catch(Exception e) { bodyJson = new JSONObject(); logger.error("getBodyJson error. ", e); } return bodyJson; } /** * 获取body字符串 * @param request * @return */ public static String getBodyStr(ServletRequest request) { String inputLine; StringBuffer buffer = new StringBuffer(); try (BufferedReader br = request.getReader()) { // while ((inputLine = br.readLine()) != null) { // buffer.append(inputLine); // } //findBug&codedex整改 LineIterator lineIter = new LineIterator(br); while (lineIter.hasNext()) { buffer.append(lineIter.next()); } } catch(Exception e) { logger.error("getBodyString error. ", e); } return buffer.toString(); } public XSSRequestWrapper(HttpServletRequest request) throws IOException { super(request); String bodyOld = getBodyStr(request); bodyOld = stripXSS(bodyOld); body = bodyOld.getBytes(); } private static String stripXSS(String value) { if (value != null) { // NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to // avoid encoded attacks. // value = ESAPI.encoder().canonicalize(value); // Avoid null characters value = value.replaceAll("", ""); // Avoid anything between script tags Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Avoid anything in a src="http://www.yihaomen.com/article/java/..." type of expression scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Remove any lonesome </script> tag scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Remove any lonesome <script ...> tag scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Avoid eval(...) expressions scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Avoid expression(...) expressions scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Avoid javascript:... expressions scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Avoid vbscript:... expressions scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); // Avoid onload= expressions scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); value = value.replaceAll("<", "<").replaceAll(">", ">"); } return value; } @Override public ServletInputStream getInputStream() throws IOException { //1、因为流的读取是一次性的,所以,对流的方法进行重写 //2、xss防御本身就要修改数据,然后将修改完成的数据从新放到request里面 final ByteArrayInputStream bais = new ByteArrayInputStream(body); return new ServletInputStream() { @Override public int read() throws IOException { return bais.read(); } @Override public void setReadListener(ReadListener arg0) { } @Override public boolean isReady() { return false; } @Override public boolean isFinished() { return false; } }; } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } }