天天看點

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 終極解決方案場景原因解決方案

4.如果是走 zuul 網關轉發通路的,隻需要在網關項目作以上設定即可,原項目可不用設定。

繼續閱讀