重名参数的bug
请求参数:
现象:
本来这里是post请求,用于上传文件,传递参数,参数是merchantId,正常讲应该只有一个37才对,
不巧的是有人新增了个权限校验
让前端统一传了merchantId,不过是在url后面加上的,
导致@RequestParam("merchantId") String merchantId在接收参数时接受到了两个merchantId,可能是被框架给拼接了
然后就变成了开头那副样子。
总结:
1.不要分别在url和body里传递同名参数,框架会自动“,”拼接参数
2.@RequestParam 可以接收get请求url里的参数,也可以接收post请求body里的参数,当然post请求多个参数也可以用@RequestBody
但是为什么会拼接,这个得看源码了。
不知道参数具体在哪里被解析的,只能倒推了。
已知
force into...
我再推..
......................................
// 解析请求头
org.apache.coyote.http11.Http11Processor#prepareRequest
// 解析配置指定的请求参数
org.apache.catalina.connector.CoyoteAdapter#postParseRequest
org.apache.catalina.connector.CoyoteAdapter#parsePathParameters
// 重点来了
org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest
org.apache.tomcat.util.http.Parameters#getParameterValues
org.apache.tomcat.util.http.Parameters#paramHashValues
// 写入参数
org.apache.tomcat.util.http.Parameters#addParameter
这个应该是url里的参数
这个应该是body里的参数。。为什么呢,因为有个 \n
往上再看一层调用栈也能发现
最后发现存储的参数竟然是这种结构
Map<String,ArrayList<String>> paramHashValues = new LinkedHashMap<>();
// 具体代码是这个
public void addParameter( String key, String value ) throws IllegalStateException {
// ........省略校验.........
ArrayList<String> values = paramHashValues.get(key);
if (values == null) {
values = new ArrayList<>(1);
paramHashValues.put(key, values);
}
values.add(value);
}
第一次传入 merchantId=37,new一个ArrayList并put k、v,然后把数组放入map中,然后在if外部修改数组
第二次传入 merchantId=37就直接get&add了,所以是 ["37", "37"]
["37", "37"] => "37,37" 也是在框架里处理的
所以,根本原因是,
同名的 key,不同的value,放到同一个Map<String,ArrayList>里了
参考:https://blog.csdn.net/weixin_43808717/article/details/118862148
三分热血值得你十二分努力。