場景
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" 參數有事先定義放行符号,預設情況下系統變量沒有該參數,是以連 |{} 三個符号也無法放行。
解決方案
一、去除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 類,複制一份出來,放到自己的項目中,注意包名不要變。
3.打開這個類,修改129行,在下圖裡面的 if 新增兩個條件: c == '[' || c == ']',重新開機一下項目就可以啦。
4.如果是走 zuul 網關轉發通路的,隻需要在網關項目作以上設定即可,原項目可不用設定。