当前位置: 首页 > article >正文

为什么过滤器需要一个 Wrapper 来 extends HttpServletRequestWrapper

为什么过滤器需要一个 Wrapper 来 extends HttpServletRequestWrapper

        • 1. HttpServletRequest` 不可直接修改
        • 2. 能够修改请求参数和请求体
        • 3. 方便扩展与重用
        • 4. 处理请求参数和请求体
        • 5. 避免对原始请求做修改
      • 典型使用场景
      • 举个例子
      • 总结

在 Java Web 开发中,过滤器(Filter)包装类(Wrapper)经常一起配合使用,尤其是在处理像 XSS 攻击这种安全问题时。通过 HttpServletRequestWrapper 或者其他类型的 Wrapper,可以在请求到达 Servlet 或 Controller 之前对其进行处理。这是因为 HttpServletRequest 类的设计原则是不可变的,因此需要通过包装类来对其进行增强或修改。
在这里插入图片描述

1. HttpServletRequest` 不可直接修改

HttpServletRequest 是一个接口,它提供了对 HTTP 请求的访问,例如获取请求参数、请求头、请求体等。这个接口的实现类(比如 HttpServletRequestImpl)是由服务器提供的,我们无法直接修改这些实现类的行为,因为它们是由容器(如 Tomcat)提供的。

然而,在 Web 开发中,特别是涉及到 XSS 防护、输入验证、日志记录等需求时,我们需要在不修改原始请求对象的基础上对其进行增强或修改。此时,HttpServletRequestWrapper 类就提供了一个方便的解决方案。

HttpServletRequestWrapperHttpServletRequest 接口的一个包装类,它允许开发人员重写 HttpServletRequest 的某些方法,从而修改请求数据(如参数、头信息等)。通过继承 HttpServletRequestWrapper,我们可以对请求进行自定义处理。

2. 能够修改请求参数和请求体

过滤器的作用是拦截请求并执行一些操作,通常是在请求被实际处理之前。例如,过滤器可以用来检查请求参数、验证请求头、检查认证信息等。

但 HTTP 请求本身是不可变的(不可直接修改),因此我们需要用一个包装类来拦截和修改请求数据。通过 HttpServletRequestWrapper,我们可以:

  • 修改请求参数(如通过 getParameterValues 方法清理 XSS 攻击)。
  • 修改请求体(例如,在 getInputStream 方法中过滤 JSON 数据)。

这样,我们可以在请求被实际处理之前对其进行修改,并确保这些修改对后续处理透明,不会破坏原本的请求流程。

3. 方便扩展与重用

通过继承 HttpServletRequestWrapper,我们可以非常方便地创建自定义的包装器。例如,XssHttpServletRequestWrapper 就是一个典型的实现,它可以对请求的参数和请求体进行 XSS 清理。这种做法的好处是:

  • 封装性:我们将 XSS 过滤的逻辑封装在一个类中,后续只需要在过滤器中应用这个包装类,就能实现统一的 XSS 防护。
  • 可扩展性:如果以后需要增加其他类型的过滤器(例如 SQL 注入过滤、URL 编码检查等),我们只需要创建相应的 HttpServletRequestWrapper 的子类即可。
4. 处理请求参数和请求体

当我们处理请求参数时,HttpServletRequestWrapper 可以重写 getParametergetParameterValuesgetParameterMap 等方法。这使得我们可以拦截并修改这些参数,而不需要修改应用程序中处理这些参数的代码。

对于请求体,HttpServletRequestWrapper 也提供了重写 getInputStream()getReader() 的能力。这使得我们能够修改请求体内容(比如过滤掉潜在的恶意脚本)。

5. 避免对原始请求做修改

通过使用 HttpServletRequestWrapper,我们可以保留原始请求对象的所有功能,同时增强其安全性和可扩展性。HttpServletRequestWrapper 并不会修改原始的请求对象,而是返回一个新的对象来包装它。这样,过滤器在处理请求时可以安全地修改或增强请求的行为,而不影响其他组件或功能。

典型使用场景

  • XSS 过滤:当请求包含用户输入(如 URL 参数、表单字段或请求体)时,可以通过包装器清理这些输入,防止恶意脚本执行。
  • 日志记录:可以通过包装器记录请求的详细信息,比如请求参数、请求头等。
  • 参数加密/解密:可以通过包装器在请求进入系统之前对敏感数据进行加密或解密。

举个例子

假设我们有一个需要进行 XSS 过滤的过滤器,可以通过 HttpServletRequestWrapper 来修改请求中的所有参数。

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    public XssHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);
        if (values != null) {
            for (int i = 0; i < values.length; i++) {
                // 进行 XSS 清理
                values[i] = cleanXss(values[i]);
            }
        }
        return values;
    }

    private String cleanXss(String value) {
        // 对 value 进行 XSS 清理处理
        return value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
    }
}

然后在过滤器中,我们就可以使用这个包装类:

public class XssFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        XssHttpServletRequestWrapper wrappedRequest = new XssHttpServletRequestWrapper(httpRequest);
        chain.doFilter(wrappedRequest, response);
    }
}

在这种方式下,我们将 XSS 过滤的逻辑封装在 XssHttpServletRequestWrapper 中,而过滤器只是简单地应用它。这使得代码更加模块化和可维护。

总结

HttpServletRequestWrapper 允许我们在不修改原始请求对象的情况下对请求进行增强或处理。这使得它非常适合在过滤器中使用,特别是在需要拦截请求并处理安全问题(如 XSS、SQL 注入等)时。通过继承 HttpServletRequestWrapper,我们可以灵活地修改请求数据、实现跨请求的安全措施,同时保持代码的清晰和可维护性。


http://www.kler.cn/a/572828.html

相关文章:

  • 神经网络为什么要用 ReLU 增加非线性?
  • DeepSeek R1模型医疗机构本地化部署评估分析(Discuss V1版上)
  • 探索IntelliJ IDEA的Tongyi Lingma插件:AI编程助手的新体验
  • Java项目中ES作为时序库
  • PHP之常量
  • 基于 Kubernetes 搭建 DevOps 持续集成环境
  • DeepSeek基础学习:深度讲解AI大模型基本原理
  • Unity:物体指定初速度、方向移动方法
  • day1 第二次入门rust
  • dify、open-webui、chatbox 对比
  • MFC扩展库BCGControlBar Pro v36.1新版亮点 - 对话框表单组件升级
  • Linux 命令终极指南:分类详解与实战场景
  • 内核编程八:基于printk宏的pr_* 宏
  • Pywinauto Recorder: 将Windows操作转化为Python脚本,高效简易地实现操作自动化
  • 【单片机通信技术】STM32 HAL库 SPI主从机通过串口发送数据
  • ASP.NET Core 3.1 修改个别API返回JSON序列化格式
  • e2studio开发RA2E1(15)----配置RTC时钟及显示时间
  • 如何排查服务器内存泄漏问题
  • Java 导出 PDF 文件:从入门到实战
  • 云上大数据平台的优化:提升效率与可靠性的实践