问题背景:最近对接第三方接口,出现了签名问题;起初接触的签名一般将url参数、请求头中的参数用以签名, 因此当遇到把body数据用以签名时走了一些弯路; 起初想法是 我这边将数据通过工具将对象转化为json字符串,对方通过框架将数据映射成实体对象,然后将实体对象转化为json,再取出url参数、请求头参数 按相同的方法进行签名。这种方式问题很明显,1、当两方使用不同的json转化工具时,转化的字符串很有可能是不一致的,如 gson的默认去除值为null的字段, jackens则仍然保留。 2、json字符串的参数排序也很难保持一直,它受制于实体对象的具体顺序。因此签名数据只能从body中取出原生字符串做签名验证,也就产生了request body数据多次读取问题。
request body数据多次读取问题处理思路:自定义一个wapper过滤器,过滤器中定义缓存用以存储body中的数据,同时呢重写read()方法,每次调用read()方法时就从缓存中读取数据,因此就解决了多次读取问题。
思路很简单,网上的例子也比较多,就不在代码、文字冗余了,粘贴两个链接以供参考:
https://cloud.tencent.com/developer/ask/82496
https://blog.csdn.net/lishaoran369/article/details/78644786
二、遇到的application/x-www-form-urlencoded问题,无法从流中取到数据 "Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"
原因:tomcat调用过getParameter(),所以只能就通过getParameter来获取数据
这种形式的提交的数据是以key=value&key2=value&…的形式传输的,和get方式类似,只不过是放在body中传输的,服务端接收数据时先判断content-Type类型,然后决定获取数据的方式,对于application/x-www-form-urlencoded类型,可以从流中或者getParameter()两种方式获取数据;数据刚开始是放在流中,可以从body流中获取(但只能消费一次,第二次在读就没有数据了),只要调用过getParameter()就不能通过流的方式获取数据;application/json只能通过body流获取数据, getParameter则获取不到。