使用servletfilter修改请求参数
现有的Web应用程序正在Tomcat 4.1上运行。 页面存在XSS问题,但我无法修改源代码。 我已经决定编写一个servletfilter来清除参数,然后才能看到页面。
我想写一个这样的Filter类:
import java.io.*; import javax.servlet.*; public final class XssFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String badValue = request.getParameter("dangerousParamName"); String goodValue = sanitize(badValue); request.setParameter("dangerousParamName", goodValue); chain.doFilter(request, response); } public void destroy() { } public void init(FilterConfig filterConfig) { } }
但是ServletRequest.setParameter
不存在。
如何在将请求传递给链之前更改请求参数的值?
正如你所说的HttpServletRequest
没有setParameter方法。 这是故意的,因为类表示来自客户端的请求,并且修改参数不会表示该请求。
一种解决scheme是使用HttpServletRequestWrapper
类,它允许你用另一个包装一个请求。 你可以inheritance它,并重写getParameter
方法来返回你的清理值。 然后,您可以将该包装的请求传递给chain.doFilter
而不是原始请求。
这有点难看,但是这就是servlet API说你应该做的。 如果你试图通过任何其他的doFilter
,一些servlet容器会抱怨你违反了规范,并会拒绝处理它。
更优雅的解决scheme是更多的工作 – 修改处理参数的原始servlet / JSP,以便它期望一个请求属性而不是参数。 filter检查参数,清理它,并设置属性(使用request.setAttribute
)与清理的值。 没有子类化,没有欺骗,但确实需要你修改应用程序的其他部分。
为了logging,这里是我最终写的课:
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 javax.servlet.http.HttpServletRequestWrapper; public final class XssFilter implements Filter { static class FilteredRequest extends HttpServletRequestWrapper { /* These are the characters allowed by the Javascript validation */ static String allowedChars = "+-0123456789#*"; public FilteredRequest(ServletRequest request) { super((HttpServletRequest)request); } public String sanitize(String input) { String result = ""; for (int i = 0; i < input.length(); i++) { if (allowedChars.indexOf(input.charAt(i)) >= 0) { result += input.charAt(i); } } return result; } public String getParameter(String paramName) { String value = super.getParameter(paramName); if ("dangerousParamName".equals(paramName)) { value = sanitize(value); } return value; } public String[] getParameterValues(String paramName) { String values[] = super.getParameterValues(paramName); if ("dangerousParamName".equals(paramName)) { for (int index = 0; index < values.length; index++) { values[index] = sanitize(values[index]); } } return values; } } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(new FilteredRequest(request), response); } public void destroy() { } public void init(FilterConfig filterConfig) { } }
编写一个简单的类,用一个getParameter()方法将HttpServletRequestWrapper
类化,该方法返回input的清理版本。 然后将HttpServletRequestWrapper
的实例直接传递给Filter.doChain()
而不是请求对象。
尝试request.setAttribute("param",value);
。 它为我工作得很好。
请find这个代码示例:
private void sanitizePrice(ServletRequest request){ if(request.getParameterValues ("price") != null){ String price[] = request.getParameterValues ("price"); for(int i=0;i<price.length;i++){ price[i] = price[i].replaceAll("[^\\dA-Za-z0-9- ]", "").trim(); System.out.println(price[i]); } request.setAttribute("price", price); //request.getParameter("numOfBooks").re } }
您可以使用正则expression式进行消毒。 在调用chain.doFilter(request,response)方法之前,在filter里面调用这个代码。 这里是示例代码:
for (Enumeration en = request.getParameterNames(); en.hasMoreElements(); ) { String name = (String)en.nextElement(); String values[] = request.getParameterValues(name); int n = values.length; for(int i=0; i < n; i++) { values[i] = values[i].replaceAll("[^\\dA-Za-z ]","").replaceAll("\\s+","+").trim(); } }