重名参数的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

posted @ 2021-11-03 16:22  夜旦  阅读(54)  评论(0编辑  收藏  举报