北京市保障性住房建设投资中心网站6,扫一扫内饰图片识别车型,制作网页设计公司,江苏山海连云建设有限公司网站
介绍
HttpServletRequestWrapper 实现了 HttpServletRequest 接口#xff0c;可以让开发人员很方便的改造发送给 Servlet 的请求.HttpServletRequest 对参数值的获取实际调的是org.apache.catalina.connector.Request没有提供对应的set方法修改属性所以不能对前端传来的参…
介绍
HttpServletRequestWrapper 实现了 HttpServletRequest 接口可以让开发人员很方便的改造发送给 Servlet 的请求.HttpServletRequest 对参数值的获取实际调的是org.apache.catalina.connector.Request没有提供对应的set方法修改属性所以不能对前端传来的参数进行修改实际场所像过滤xss攻击取认证token统一去除token前缀等需要进行请求参数的处理此时HttpServletRequestWrapper 就应运而生了。应用了装饰模式.HttpServletRequestWrapper 采用装饰者模式对HttpServletRequest进行包装我们可以通过继承HttpServletRequestWrapper 类去重写getParameterValuesgetParameter等方法实际还是调用HttpServletRequest的相对应方法但是可以对方法的结果进行改装。一般要和 Filter 配合应用
应用场景
需要修改客户端请求参数的场合例如
将不支持的语言参数修改为默认语言将加密的 DeviceId 解密并解析出其中的 imei 和 sn同时在客户端请求里添加这 2 个参数 ** deviceId hex(rc4(imei ‘_’ sn))
示例
就以上面所说的解密 DeviceId 为例
web.xml 配置
添加一个解析 DeviceId 的 Filter
!-- 解析加密的 deviceId 得到 imei 和 sn --filterfilter-namedeviceIdParseFilter/filter-namefilter-classcom.xxxxxx.DeviceIdParseFilter/filter-classinit-paramparam-nameencoding/param-nameparam-valueUTF-8/param-value/init-paraminit-paramparam-nameforceEncoding/param-nameparam-valuetrue/param-value/init-param/filterfilter-mappingfilter-namedeviceIdParseFilter/filter-nameurl-pattern*.do/url-pattern/filter-mappingFilter 代码
public class DeviceIdParseFilter implements Filter {private static final String KEY xxxxxxx;private static final Logger log Logger.getLogger(DeviceIdParseFilter.class);private static final String[] DEFAULT_RESULT {,};Overridepublic void init(FilterConfig filterConfig) throws ServletException {}Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {String deviceId request.getParameter(deviceId);if (deviceId ! null deviceId.length() 0) {String[] result parseDeviceId(deviceId);DeviceIdParseRequest req new DeviceIdParseRequest((HttpServletRequest) request,result[0], result[1]);chain.doFilter(req, response);} else {chain.doFilter(request, response);}}/*** * 从 deviceId 里解析出 imei 和 sn* * imei result[0]* sn result[1]* * * param deviceId* return*/private static final String[] parseDeviceId(String deviceId) {try {String src Rc4Util.decrypt(deviceId, KEY);if (src.indexOf(_) 0) {return src.split(_);}} catch (Exception e) {log.error(e, e);}return DEFAULT_RESULT;}Overridepublic void destroy() {}}
这个 Filter 会将包含 deviceId 参数的请求进行如下处理
将 deviceId 的值用 RC4 进行解密从解密出来的 deviceId 里解析出 imei 和 sn将请求改造成 DeviceIdParseRequest这就是我们的 HttpServletRequestWrapper 而不包含 deviceId 参数的请求不做任何处理
HttpServletRequestWrapper 代码
public class DeviceIdParseRequest extends HttpServletRequestWrapper {private String imei;private String sn;/*** param request*/public DeviceIdParseRequest(HttpServletRequest request) {super(request);this.imei ;this.sn ;}/*** param request* param imei* param sn*/public DeviceIdParseRequest(HttpServletRequest request, String imei, String sn) {super(request);this.imei imei;this.sn sn;}Overridepublic String getParameter(String name) {if (imei.equals(name)) {return imei;} else if (sn.equals(name)) {return sn;} else {return super.getParameter(name);}}Overridepublic String[] getParameterValues(String name) {if (imei.equals(name)) {return new String[] { imei };} else if (sn.equals(name)) {return new String[] { sn };} else {return super.getParameterValues(name);}}}这里针对 imei 和 sn 进行了特殊处理返回的不是客户端提交的参数而是在 Filter 里通过解析 deviceId 得到的 imei 和 sn
需要注意的是
如果用 request.getParameter() 获取客户端请求参数的值那么只需要重写该方法就行了如果用 SpringMVC 的 RequestParam 注解来获取请求参数的值那么需要重写 getParameterValues 方法因为 SpringMVC 是用这个方法来获取参数值的
运行结果
用于测试的 controller
这个测试类把接收到的参数直接返回
Controller
RequestMapping(/api/)
public class TestController {ResponseBodyRequestMapping(test.do)public Result test(String deviceId, String imei, String sn) {MapString, String map new HashMap();map.put(deviceId, deviceId);map.put(imei, imei);map.put(sn, sn);return new Result(map);}}
请求参数不包含 deviceId.请求 url 如下
http://xxxxx.in.xxxxx.com/api/test.do?reqno123456imeiimeisn1001modelmx6osflyme6ver1.0.0localeen_US返回结果
{code: 200,message: ,redirect: ,value: {sn: 1001,imei: imei,deviceId: null}
}请求参数包含 deviceId。请求 url
http://xxxxxxx.com/api/test.do?reqno123456sn1001modelmx6osflyme6ver1.0.0localeen_USdeviceId7cfbf5cbd70bcf1c006d7d0aa77688518444497a2b45683ea41ce690e92d6d38返回结果
{code: 200,message: ,redirect: ,value: {sn: 111,imei: org.testng.annotations.Test;,deviceId: 7cfbf5cbd70bcf1c006d7d0aa77688518444497a2b45683ea41ce690e92d6d38}
}可以看到
请求参数里不存在的 imei 能获取到值请求参数里存在的 sn 值被修改了