请求参数:

重名参数的bug_post请求

现象:

重名参数的bug_post请求_02

本来这里是post请求,用于上传文件,传递参数,参数是merchantId,正常讲应该只有一个37才对,

不巧的是有人新增了个权限校验

重名参数的bug_tomcat_03

让前端统一传了merchantId,不过是在url后面加上的,

导致@RequestParam("merchantId") String merchantId在接收参数时接受到了两个merchantId,可能是被框架给拼接了

重名参数的bug_post请求_04

然后就变成了开头那副样子。

重名参数的bug_bug_05

总结:

1.不要分别在url和body里传递同名参数,框架会自动“,”拼接参数

2.@RequestParam 可以接收get请求url里的参数,也可以接收post请求body里的参数,当然post请求多个参数也可以用@RequestBody

但是为什么会拼接,这个得看源码了。

不知道参数具体在哪里被解析的,只能倒推了。

已知

重名参数的bug_post请求_06

force into...

重名参数的bug_apache_07

我再推..

重名参数的bug_bug_08

......................................

// 解析请求头

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


重名参数的bug_tomcat_09

这个应该是url里的参数

重名参数的bug_bug_10

这个应该是body里的参数。。为什么呢,因为有个 \n

往上再看一层调用栈也能发现

重名参数的bug_post请求_11

最后发现存储的参数竟然是这种结构

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>里了


三分热血值得你十二分努力。