自定一个请求处理类继承HttpServletRequestWrapper类,重写各个请求参数的获取方法,在方法里面使用正则匹配过滤掉特殊的符号:
1public class XSSHttpServletRequestWrapper extends HttpServletRequestWrapper { 2 /** 3 * Constructs a request object wrapping the given request. 4 * 5 * @param request The request to wrap 6 * @throws IllegalArgumentException if the request is null 7 */ 8 public XSSHttpServletRequestWrapper(HttpServletRequest request) { 9 super(request); 10 } 11 12 /** 13 * 对数组参数进行特殊字符过滤 14 */ 15 @Override 16 public String[] getParameterValues(String name) { 17 String[] values = super.getParameterValues(name); 18 if (values == null) { 19 return null; 20 } 21 int count = values.length; 22 String[] encodedValues = new String[count]; 23 for (int i = 0; i < count; i++) { 24 encodedValues[i] = cleanXSS(values[i]); 25 } 26 return encodedValues; 27 } 28 29 /** 30 * 对参数中特殊字符进行过滤 31 */ 32 @Override 33 public String getParameter(String name) { 34 String value = super.getParameter(name); 35 if (value == null) { 36 return null; 37 } 38 return cleanXSS(value); 39 } 40 41 /** 42 * 获取attribute,特殊字符过滤 43 */ 44 @Override 45 public Object getAttribute(String name) { 46 Object value = super.getAttribute(name); 47 if (value != null && value instanceof String) { 48 cleanXSS((String) value); 49 } 50 return value; 51 } 52 53 /** 54 * 对请求头部进行特殊字符过滤 55 */ 56 @Override 57 public String getHeader(String name) { 58 String value = super.getHeader(name); 59 if (value == null) { 60 return null; 61 } 62 return cleanXSS(value); 63 } 64 65 private String cleanXSS(String value) { 66 if (value != null) { 67 //推荐使用ESAPI库来避免脚本攻击,value = ESAPI.encoder().canonicalize(value); 68 // 避免空字符串 69 value = value.replaceAll(" ", ""); 70 // 避免script 标签 71 Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE); 72 value = scriptPattern.matcher(value).replaceAll(""); 73 // 避免src形式的表达式 74 scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", 75 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 76 value = scriptPattern.matcher(value).replaceAll(""); 77 scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", 78 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 79 value = scriptPattern.matcher(value).replaceAll(""); 80 // 删除单个的 </script> 标签 81 scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE); 82 value = scriptPattern.matcher(value).replaceAll(""); 83 // 删除单个的<script ...> 标签 84 scriptPattern = Pattern.compile("<script(.*?)>", 85 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 86 value = scriptPattern.matcher(value).replaceAll(""); 87 // 避免 eval(...) 形式表达式 88 scriptPattern = Pattern.compile("eval\\((.*?)\\)", 89 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 90 value = scriptPattern.matcher(value).replaceAll(""); 91 // 避免 expression(...) 表达式 92 scriptPattern = Pattern.compile("expression\\((.*?)\\)", 93 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 94 value = scriptPattern.matcher(value).replaceAll(""); 95 // 避免 javascript: 表达式 96 scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE); 97 value = scriptPattern.matcher(value).replaceAll(""); 98 // 避免 vbscript:表达式 99 scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE); 100 value = scriptPattern.matcher(value).replaceAll(""); 101 // 避免 οnlοad= 表达式 102 scriptPattern = Pattern.compile("onload(.*?)=", 103 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 104 value = scriptPattern.matcher(value).replaceAll(""); 105 } 106 return value; 107 } 108}
定义过滤器:
1public class XSSHttpServletRequestFilter implements Filter { 2 private final Logger logger = LoggerFactory.getLogger(getClass()); 3 4 @Override 5 public void init(FilterConfig filterConfig) throws ServletException { 6 logger.info("##init XSSFilter"); 7 } 8 9 @Override 10 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 11 try { 12 //将请求转换为 自定义的请求包装类 13 chain.doFilter(new XSSHttpServletRequestWrapper((HttpServletRequest) request), response); 14 } catch (Exception e) { 15 throw e; 16 } 17 } 18 19 @Override 20 public void destroy() { 21 logger.info("##destroy XSSFilter"); 22 } 23}
将过滤器注册到spring的bean容器中:
1@Bean 2public FilterRegistrationBean xSSHttpServletRequestFilterRegistrationBean() { 3 FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); 4 filterRegistrationBean.setFilter(new XSSHttpServletRequestFilter()); 5 filterRegistrationBean.setName("xSSHttpServletRequestFilter"); 6 filterRegistrationBean.setUrlPatterns(Arrays.asList("/xxx")); 7 filterRegistrationBean.setOrder(1); 8 return filterRegistrationBean; 9}
这里使用的springboot,如果是spring,相当于在web.xml中加入一下配置:
1<filter> 2 <filter-name>xSSHttpServletRequestFilter</filter-name> 3 <filter-class>com.xxx.xxx.xxxx.XSSHttpServletRequestFilter</filter-class> 4</filter> 5<filter-mapping> 6 <filter-name>xSSHttpServletRequestFilter</filter-name> 7 <url-pattern>/xxx</url-pattern> 8</filter-mapping>