Spring Boot请求报RFC非法字符 数组查询参数接收为null排查
问题描述
携带数组类型查询参数的请求URL如下:
http://127.0.0.1:3009/mac/view/:userId?ot-replace[0]=kin43
对应的Controller层代码如下:
@GetMapping(value = "/{userId}/**") public ResponseEntity<String> viewObject(@PathVariable(value = "userId") String uId, HttpServletRequest request, @RequestParam(name="ot-replace", required=false)String[] regexReplace ) {}
初次访问接口时抛出如下错误:
Invalid character found in the request target The valid characters are defined in RFC 7230 and RFC 3986
问题更新
添加Tomcat配置放行特殊字符后:
server.tomcat.relaxed-query-chars=[,]
非法字符报错不再出现,但接口中定义的regexReplace参数始终接收到null值。
问题根因
- 初始RFC合规报错:Tomcat 8.5及以上版本默认严格执行RFC 3986规范校验请求目标,
[、]属于URL保留字符,未编码直接出现在查询串中会被判定为非法字符,直接抛出校验错误。 - 放行特殊字符后参数取null:Spring MVC默认的
@RequestParam参数绑定只会匹配参数名与name属性完全一致的查询参数,无法自动识别参数名[索引]这种带下标后缀的数组传参格式,因此找不到名为ot-replace的参数,最终赋值为null。
可行解决方案
方案1:调整数组传参格式(推荐,无兼容问题)
直接使用同名重复参数的标准数组传参格式,不需要额外配置Tomcat字符放行规则,完全符合URL规范,Spring MVC可自动完成数组绑定:
请求URL示例:
http://127.0.0.1:3009/mac/view/1001?ot-replace=kin43&ot-replace=otherVal1&ot-replace=otherVal2
该格式下接口原有@RequestParam配置无需任何修改,regexReplace数组可直接接收到所有传入的参数值,也不会触发Tomcat的RFC校验错误。
方案2:兼容现有带下标的传参格式
如果业务侧必须保留ot-replace[0]这类带下标索引的传参格式,除已配置的Tomcat特殊字符放行规则外,可通过两种方式获取参数:
- 接口内手动提取参数:直接遍历请求参数名,匹配所有符合
ot-replace[*]格式的参数收集即可,示例代码:
@GetMapping(value = "/{userId}/**") public ResponseEntity<String> viewObject(@PathVariable(value = "userId") String uId, HttpServletRequest request) { List<String> replaceValList = new ArrayList<>(); Enumeration<String> paramNames = request.getParameterNames(); while (paramNames.hasMoreElements()) { String paramName = paramNames.nextElement(); if (paramName.matches("ot-replace\\[\\d+\\]")) { replaceValList.add(request.getParameter(paramName)); } } String[] regexReplace = replaceValList.toArray(new String[0]); // 执行业务逻辑 return ResponseEntity.ok("success"); }
- 全局自定义参数解析器:如果多个接口都需要兼容该类带下标的数组传参,可实现Spring的
HandlerMethodArgumentResolver接口,自定义匹配逻辑完成数组参数自动绑定,注册到MVC配置后即可和原有@RequestParam一样使用。
内容的提问来源于stack exchange,提问作者WISHY
相关产品推荐
相关产品推荐

