HttpServletRequestWrapper类的作用

Servlet规范中中引入的filter是非常有用的,因为它引入了一个功能强大的拦截模式。
filter是这样的一种java对象。它可以在request到达servlet之前拦截HttpServletRequest对象,也可以在服务方法转移控制后拦截HttpServletResponse对象。
我们可以使用filter对象完成的任务有:检查用户的输入、以及压缩web内容。
但是,当我们在使用filter的时候却会发现至少有一半的时间我们都想改变HttpServletRequest对象的参数。如:用filter在HttpServletRequest对象到达Servlet之前将用户输入的空格去掉。但是由于java.util.Map包装的HttpServletRequest对象的参数是不可改变的,那要怎么办呢?
幸运的是,尽管我们不能改变对象本身,但是可以通过装饰模式来改变其状态。
image.png
因此,想要改变在httpServletRequest中的参数,可以通过httpServletRequest的装饰类HttpServletRequestWrapper来实现,只需要在装饰类中按照需要重写其getParameter(getParameterValues)方法即可。

示例使用 HttpServletRequestWrapper 解决XSS 攻击问题:

(1)继承 HttpServletRequestWrapper ,重写HttpServletRequestWrapper中的getParameter方法:

  1. public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
  2. private HttpServletRequest request;
  3. public XssHttpServletRequestWrapper(HttpServletRequest request) {
  4. super(request);
  5. this.request=request;
  6. }
  7. @Override
  8. public String getParameter(String name) {
  9. // 获取之前的参数
  10. String value = super.getParameter(name);
  11. String newValue="";
  12. if(StringUtils.isNotEmpty(value)){
  13. newValue = StringEscapeUtils.escapeHtml(value);
  14. }
  15. return newValue;
  16. }
  17. }

(2)实现 Filter 拦截所有请求:

  1. @WebFilter(filterName = "XSSFilter", urlPatterns = "/*")
  2. public class XSSFilter implements Filter{
  3. @Override
  4. public void init(FilterConfig filterConfig) throws ServletException {
  5. }
  6. @Override
  7. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  8. // 1. 使用过滤器拦截所有参数
  9. HttpServletRequest req = (HttpServletRequest) servletRequest;
  10. // 2.重新getParameter方法
  11. XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper(req);
  12. // 放行程序,继续往下执行
  13. filterChain.doFilter(xssHttpServletRequestWrapper, servletResponse);
  14. }
  15. @Override
  16. public void destroy() {
  17. }
  18. }

(3)注意点 (项目是基于Spring boot的话需要加上@ServletComponentScan不然找不到Filter)
image.png