SpringBoot 中 The valid characters are defined in RFC 7230 and RFC 3986 终极解决方案

场景

springboot(2.0.4)使用内置 tomcat(8.5.32),  在GET请求中含有特殊字符 [ ] 时报错:

java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986

原因

tomcat 版本在8.0.x左右的时候,tomcat.util.http.parser.HttpParser这个类下有对请求地址中的特殊符号进行处理,这里面预留的是{}| 三个符号,并且是需要先配置在系统变量下面的 "tomcat.util.http.parser.HttpParser.requestTargetAllow" 参数有事先定义放行符号,默认情况下系统变量没有该参数,所以连 |{} 三个符号也无法放行。

SpringBoot 中 The valid characters are defined in RFC 7230 and RFC 3986 终极解决方案

解决方案

一、去除URL中的特殊字符。

最简单粗暴。

二、使用 POST 方法提交数据

如果场景没有限制 可以改成POST的话就选这个。

三、更换低版本的Tomcat

更换7.x.x版本的tomcat,springboot内置的tomcat版本是固定的,同时需要更换springboot版本。这个不太建议,万一又出什么其他幺蛾子。

四、新增配置

在springboot项目的启动类main方法上新增如下系统变量,位置在run方法前后都可以,因为tomcat过滤请求地址是实时取系统变量,只要有设进去就行。

System.setProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow","{}");

在此有个误区:有看到其他人写的是在properties里面配置

tomcat.util.http.parser.HttpParser.requestTargetAllow={},这样我尝试过是不行的,应该是因为这边去的是系统变量,两份配置是不一样的。

ps:万一想用除 |{} 外的其他源码中非预留的符号,比如 [ ] 

1.先在springboot项目的启动类main方法上新增系统变量

System.setProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow","{}");

2.在源码中找到 org.apache.tomcat.util.http.parser 包下面的 HttpParser 类,复制一份出来,放到自己的项目中,注意包名不要变。

SpringBoot 中 The valid characters are defined in RFC 7230 and RFC 3986 终极解决方案

3.打开这个类,修改129行,在下图里面的 if 新增两个条件:  c == '[' || c == ']',重启一下项目就可以啦。

 SpringBoot 中 The valid characters are defined in RFC 7230 and RFC 3986 终极解决方案

SpringBoot 中 The valid characters are defined in RFC 7230 and RFC 3986 终极解决方案