用 HttpServletRequestWrapper 定制客户端请求参数

介绍

  • HttpServletRequestWrapper 实现了 HttpServletRequest 接口,可以让开发人员很方便的改造发送给 Servlet 的请求

  • 应用了装饰模式

  • 一般要和 Filter 配合应用

应用场景

需要修改客户端请求参数的场合,例如

  • 将不支持的语言参数修改为默认语言

  • 将加密的 DeviceId 解密,并解析出其中的 imei 和 sn,同时在客户端请求里添加这 2 个参数

    • deviceId = hex(rc4(imei + '_' + sn))

示例

就以上面所说的解密 DeviceId 为例

web.xml 配置

添加一个解析 DeviceId 的 Filter

<!-- 解析加密的 deviceId 得到 imei 和 sn -->
<filter>
    <filter-name>deviceIdParseFilter</filter-name>
    <filter-class>com.meizu.browser.app.common.DeviceIdParseFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>deviceIdParseFilter</filter-name>
    <url-pattern>*.do</url-pattern>
</filter-mapping>

Filter 代码

这个 Filter 会将包含 deviceId 参数的请求进行如下处理

  1. 将 deviceId 的值用 RC4 进行解密

  2. 从解密出来的 deviceId 里解析出 imei 和 sn

  3. 将请求改造成 DeviceIdParseRequest,这就是我们的 HttpServletRequestWrapper

而不包含 deviceId 参数的请求不做任何处理

HttpServletRequestWrapper 代码

这里针对 imei 和 sn 进行了特殊处理,返回的不是客户端提交的参数,而是在 Filter 里通过解析 deviceId 得到的 imei 和 sn

需要注意的是

  • 如果用 request.getParameter() 获取客户端请求参数的值,那么只需要重写该方法就行了

  • 如果用 SpringMVC 的 @RequestParam 注解来获取请求参数的值,那么需要重写 getParameterValues 方法:因为 SpringMVC 是用这个方法来获取参数值的

运行结果

用于测试的 controller

这个测试类把接收到的参数直接返回

请求参数不包含 deviceId

请求 url

返回结果

请求参数包含 deviceId

请求 url

返回结果

可以看到

  • 请求参数里不存在的 imei 能获取到值

  • 请求参数里存在的 sn 值被修改了

附录

关于 RC4 加密算法

deviceId 的加解密用到了 RC4 算法,下面是相应的代码

Last updated