What is `HttpServletRequestWrapper` does?

这篇具有很好参考价值的文章主要介绍了What is `HttpServletRequestWrapper` does?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

HttpServletRequestWrapperJava Servlet API 中的一个类,作为 HttpServletRequest 接口的包装器(Decorator)实现。

该类设计为装饰者模式(Decorator Pattern)的一部分,允许开发人员通过包装现有的 HttpServletRequest对象来定制或修改请求行为。比如:
1、过滤或修改请求参数
2、添加或删除请求头信息
3、实现请求级的安全控制,如防止 XSS(跨站脚本攻击)或 SQL 注入等安全风险
4、转换请求体数据
5、修改请求URI或其他请求属性

What is `HttpServletRequestWrapper` does?,框架,网络编程,java
样例:获取requestBody的内容
2、添加或删除请求头信息
3、实现请求级的安全控制,如防止 XSS(跨站脚本攻击)或 SQL 注入等安全风险

import com.zhangziwa.practisesvr.utils.stream.StreamIUtils;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.text.StringEscapeUtils;

import java.io.*;

public class FilterHttpRequestBodyWrapper extends HttpServletRequestWrapper {
    private final byte[] bodyByteArr; // 字节数组
    private final ByteArrayInputStream byteArrayInputStream; // 从字节数组读取数据的输入流

    private BufferedReader bufferedReader; // getReader()
    private ServletInputStream servletInputStream; // getInputStream()

    public FilterHttpRequestBodyWrapper(HttpServletRequest request) throws IOException {
        super(request);
        bodyByteArr = StreamIUtils.readStream2Bytes(request.getInputStream());
        byteArrayInputStream = new ByteArrayInputStream(bodyByteArr);
    }

    public String getBodyByteArr() throws UnsupportedEncodingException {
        return new String(bodyByteArr, getCharacterEncoding());
    }

    /**
     * 覆盖父类方法,实现获取参数时自动对参数值进行XSS攻击过滤。
     *
     * @param name 参数名
     * @return 如果参数存在,则返回经过HTML转义的、已过滤XSS攻击的参数值;若参数不存在,则返回null
     */
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (value != null) {
            // 使用StringEscapeUtils.escapeHtml4对请求参数进行XSS攻击过滤
            return StringEscapeUtils.escapeHtml4(value);
        }
        return null;
    }

    /**
     * 重写父类的getCharacterEncoding方法,获取请求的字符编码。
     * 若当前请求的字符编码未设置或为空,则默认返回"utf-8"作为字符编码。
     *
     * @return 请求的字符编码,若原编码为空则返回"utf-8"
     */
    @Override
    public String getCharacterEncoding() {
        String encoding = super.getCharacterEncoding();
        return encoding == null ? "utf-8" : encoding;
    }

    /**
     * 重写父类或接口中的getReader方法,提供一个BufferedReader对象。
     *
     * @return 返回一个根据请求体内容和字符编码方式创建的BufferedReader对象
     */
    @Override
    public BufferedReader getReader() {
        if (bufferedReader == null) {
            try {
                // 封装一个BufferedReader对象以提高读取效率
                bufferedReader = new BufferedReader(new InputStreamReader(byteArrayInputStream, getCharacterEncoding()));
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("Unsupported encoding: ", e);
            }
        }
        return bufferedReader;
    }

    /**
     * 重写父类的 getInputStream 方法,提供一个自定义的 ServletInputStream 实例,
     * 该实例从内部的 byteArrayInputStream 中读取数据,并支持监听器模式。
     *
     * @return 自定义的 ServletInputStream 实例,用于读取请求体数据
     */
    @Override
    public ServletInputStream getInputStream() {
        // 确保 servletInputStream 的初始化在多线程环境下是安全的
        if (servletInputStream == null) {
            synchronized (this) {
                // 创建并初始化一个 ServletInputStream 子类实例
                servletInputStream = new ServletInputStream() {
                    /**
                     * 从内部的 byteArrayInputStream 中读取下一个字节数据
                     *
                     * @return 下一个可读字节,如果已到达流末尾则返回 -1
                     * @throws IOException 如果发生输入/输出错误
                     */
                    @Override
                    public int read() throws IOException {
                        return byteArrayInputStream.read();
                    }

                    /**
                     * 判断是否已经读取完所有数据,即 byteArrayInputStream 是否还有可用数据
                     *
                     * @return 如果没有更多数据可供读取,则返回 true;否则返回 false
                     */
                    public boolean isFinished() {
                        return byteArrayInputStream.available() == 0;
                    }

                    /**
                     * 指示此输入流是否准备好进行读取操作
                     *
                     * @return 始终返回 true,表示此输入流始终处于就绪状态
                     */
                    public boolean isReady() {
                        return true;
                    }

                    /**
                     * 设置 ReadListener 监听器,用于异步读取数据。此处未实现具体逻辑。
                     *
                     * @param readListener 用于处理数据读取事件的 ReadListener 实例
                     */
                    @Override
                    public void setReadListener(ReadListener readListener) {
                    }
                };
            }
        }
        return servletInputStream;
    }
}
# 使用
FilterHttpRequestBodyWrapper filterHttpRequest = new FilterHttpRequestBodyWrapper(httpRequest);
String body = filterHttpRequest.getBodyByteArr();
filterHttpRequest.setAttribute("requestBodyData", body);

# 继续执行filter链
chain.doFilter(filterHttpRequest, response);

样例:获取requestBody的内容
4、转换请求体数据

import com.zhangziwa.practisesvr.model.Student;
import com.zhangziwa.practisesvr.utils.JsonUtils;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * StudentParamHttpRequestWrapper 是一个自定义的 HttpServletRequest 包装类,它继承或实现 HttpRequestWrapper 类,
 * 主要用于在处理 HTTP 请求时对学生的特定参数进行封装和预处理。此类允许开发者方便地获取、验证以及修改请求中的学生相关参数,
 * 提供了一种集中管理与学生信息相关的请求参数的方式。
 * 它主要用于解决以下问题:
 * 1. 对请求参数的统一管理和验证,例如检查学号(studentId)、姓名(name)等字段的有效性。
 * 2. 在过滤器、拦截器或控制器中便捷地访问和操作学生相关信息,无需重复解析原始请求参数。
 * 注意:此包装类的具体实现可能需要根据实际项目需求来调整。
 */
public class StudentParamHttpRequestWrapper extends HttpServletRequestWrapper {
    private final String body;

    public StudentParamHttpRequestWrapper(HttpServletRequest request, Student vo) {
        super(request);
        this.body = JsonUtils.toJson(vo);
    }

    @Override
    public String getCharacterEncoding() {
        String encoding = super.getCharacterEncoding();
        return encoding == null ? "utf-8" : encoding;
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes(getCharacterEncoding()));
        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }

            public boolean isFinished() {
                return byteArrayInputStream.available() == 0;
            }

            public boolean isReady() {
                return true;
            }

            @Override
            public void setReadListener(ReadListener readListener) {
            }
        };
    }
}
# 使用
StudentParamHttpRequestWrapper filterHttpRequest = new StudentParamHttpRequestWrapper(httpRequest, new Student());
chain.doFilter(filterHttpRequest, response);

[Ref] StreamIUtils 共通方法最佳实践文章来源地址https://www.toymoban.com/news/detail-799461.html

到了这里,关于What is `HttpServletRequestWrapper` does?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • What is `@Repository` does?

    @Repository 是 Spring 注解,标识数据访问层组件( DAO, Data Access Object ) 当一个类被标记为 @Repository 时: 1、组件扫描与自动代理: Spring 通过组件扫描( Component Scan )机制发现带有 @Repository 的类,并将其纳入 Spring IoC容器 管理,创建对应的 Bean实例 。 2、异常处理增强: Spri

    2024年01月16日
    浏览(44)
  • What is `@Controller` does?

    @Controller 是 SpringMVC 注解,标记一个类作为 Web控制器(Controller) ,负责处理 HTTP请求 并返回 响应结果 在 SpringMVC 中,控制器类的主要职责是: 1、接收来自客户端的 HTTP请求 2、 调用 服务层或其他业务逻辑组件 3、根据操作结果准备 视图模型数据(Model) ,将控制权转移给

    2024年01月17日
    浏览(46)
  • What is `XSS` does?

    跨站脚本攻击(Cross-Site Scripting,XSS) 是一种针对网站应用程序的安全漏洞,允许攻击者将 恶意脚本 注入到其他用户查看的网页中。当这些用户访问受感染的页面时,他们的浏览器会执行这些恶意脚本,导致各种安全问题的发生,如 窃取用户的会话信息 、 cookie 或 其他敏感

    2024年01月21日
    浏览(47)
  • What is `addArgumentResolvers` does in `WebMvcConfigurer` ?

    addArgumentResolvers 在 SpringMVC 框架中,主要用于向 Spring容器 注册自定义的参数解析器。在处理 HTTP请求 时, SpringMVC 会使用这些参数解析器将请求中的数据(如查询参数、路径变量、表单数据等)转换并注入到控制器方法的参数中。 http://localhost:8080/customDateArgumentResolver?date=20

    2024年02月01日
    浏览(108)
  • What is `StringEscapeUtils.escapeHtml4` does?

    StringEscapeUtils.escapeHtml4 作用是将 特殊字符 转换为它们对应的 HTML实体形式 ,从而防止这些字符在网页中被解析为 HTML标签 或 脚本 ,有助于防止 跨站脚本攻击(XSS, Cross-Site Scripting) 对于现代Web应用来说,建议使用更全面的安全策略来防止XSS攻击,而不仅仅是依赖于这种简单

    2024年01月18日
    浏览(44)
  • What does `$?` do?

    shell 中 $? 是一个特殊的内置变量,可以获取最后一次执行命令的退出状态。 在执行shell函数后, $? 返回函数中最后一次执行命令的退出状态。 在执行shell脚本后, $? 返回脚本中最后一次执行命令的退出状态。 [Ref] Shell 脚本中的exit状态解释

    2024年02月01日
    浏览(42)
  • What does `rpm -ivh` do?

    rpm -ivh 安装 并 显示安装进度 ( –install–verbose–hash ) [Ref] rpm -uvh和-ivh有什么区别以及zabbix 安装部署及php升级 rpm 执行安装包 分 二进制包(Binary) 以及 源代码包(Source) 两种 二进制包(Binary) 可以直接安装在计算机中 源代码包(Source) 包将会由 RPM 自动编译、安装。源代

    2024年02月02日
    浏览(46)
  • 【Linux网络编程一】网络基础1(网络框架)

    本篇开始总结网络知识,系统部分到此结束。 网络的本质就是在获取和生产数据,而系统的本质就是在处理数据。从网络中获取到数据利用系统调用来处理数据。而网络的本质也就是文件,我往文件里写,就是往网卡里写,往网卡里写,就是往网络里写。 我们在生活中都是

    2024年02月19日
    浏览(39)
  • C语言网络编程:实现自己的高性能网络框架

    一般生产环境中最耗时的其实是业务逻辑处理。所以,是不是可以将处理业务逻辑的代码给拆出来丢到线程池中去执行。 比如像下面这样: ​我们事先创建好一堆worker线程,主线程accepter拿到一个连接上来的套接字,就从线程池中取出一个线程将这个套接字交给它。这样,我

    2024年02月10日
    浏览(47)
  • Java 网络编程 —— RMI 框架

    RMI 是 Java 提供的一个完善的简单易用的远程方法调用框架,采用客户/服务器通信方式,在服务器上部署了提供各种服务的远程对象,客户端请求访问服务器上远程对象的方法,它要求客户端与服务器端都是 Java 程序 RMI 框架采用代理来负责客户与远程对象之间通过 Socket 进行

    2024年02月09日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包