从流中读取application/json格式的参数之后,request中信息不完整
在公司写验签的时候,遇到了一个问题:
用post请求,application/json形式的时候,request要想获取参数,只能用流的形式,但是这样造成的问题是,我把参数从流中拿出来消耗之后,request中就没有了参数的信息,这样就达不到验签(验证请求是否正确,不会操作请求的任何信息,请求照样向后传递)的效果了。所以从网上找到了一个解决方法,并用过滤器来实现这个验签,放弃用拦截器实现的想法,就成了。在这里给大家分享出来,希望可以有帮助。
文章写的很好,相信大家可以理解。
文章如下:
获取请求对象中的数据流,通过解析流信息来获取提交的内容;代码示例如下:
通过这种简单的解析方式,将http请求中的body解析成 字符串的形式;然后再对字符串的格式进行业务解析;
这种处理方式的优点是:能解析 出content-Type 为 application/x-www-form-urlencoded ,application/json , text/xml 这三种提交方式的 数据
但是这种方式有一个很大的缺点:那就是当从请求中获取流以后,流被filter中的这个 inputStreamToString(InputStream in) 这个方法处理后就被“消耗”了,这会导致,chain.doFilter(request, res)这个链在传递 request对象的时候,里面的请求流为空,导致责任链模式下,其他下游的链无法获取请求的body,从而导致程序无法正常运行,这也使得我们的这个filter虽然可以获取请求信息,但是它会导致整个应用程序不可用,那么它也就失去了意义;
针对缺陷:流一旦被读取,就无法向下传递整个问题,有如下解决方案;
解决思路如下:将取出来的字符串,再次转换成流,然后把它放入到新request 对象中,在chain.doFiler方法中 传递新的request对象;要实现这种思路,需要自定义一个类
继承HttpServletRequestWrapper,然后重写public BufferedReader getReader()方法,public ServletInputStream getInputStream()方法;(这两个方法的重写实现逻辑如下:getInputStream()方法中将body体中的字符串转换为字节流(它实质上返回的是一个ServletInputStream 对象);然后通过getReader()调用---->getInputStream()方法;),继承实现重写逻辑以后,在自定义分filter(VersionCheckFilter)中,使用自定义的HttpServletRequestWrapper(BodyReaderHttpServletRequestWrapper)将原始的HttpServletRequest对象进行再次封装;再通过BodyReaderHttpServletRequestWrapper对象去做dofilter(req,res)的req对象;
涉及的三个类的代码如下:
自定义的HttpServletRequestWrapper
2、辅助类
HttpHelper
3、自定义的filter
更多推荐
所有评论(0)