終極解決方案: Invalid character found in the request target. The valid characters are defined in RFC 3986
25-Aug-2018 11:27:27.086 信息 [http-nio-8087-exec-5] org.apache.coyote.http11.Http11Processor.service Error parsing HTTP request header
Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:479)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:684)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
從錯誤日志中看到Error parsing HTTP request header
負(fù)責(zé)解析http請求的是org.apache.tomcat.util.http.parser.HttpParser
媒佣,它對請求對URL中對字符做了限制蒿秦,具體代碼如下:
IS_NOT_REQUEST_TARGET[]中定義了一堆not request target
if(IS_CONTROL[i] || i > 127 || i == 32 || i == 34 || i == 35 || i == 60 || i == 62 || i == 92 || i == 94 || i == 96 || i == 123 || i == 124 || i == 125) {
IS_NOT_REQUEST_TARGET[i] = true;
}
轉(zhuǎn)換過來就是以下字符(對應(yīng)10進制ASCII),也就是URL中不能包含的特殊字符:
鍵盤上那些控制鍵:(<32或者=127)
非英文字符(>127)
空格(32)
雙引號(34)
#(35)
<(60)
>(62)
反斜杠(92)
^(94)
TAB上面那個鍵,~(96)
{(123)
}(124)
|(125)
我碰到這個問題也搗弄了半天朗恳,參照其他的各種解決方案都不行涧窒。并且我是使用了多種特殊字符肌似,運用單一某種方案還不能完全奏效棵里。下面是經(jīng)過實踐的解決方案义黎,請按順序讀完禾进。
解決辦法(親測)
在conf/catalina.properties中最后添加2行:
tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}
org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
該方式,在所有Tomcat版本均適用廉涕。
解析:在執(zhí)行請求時泻云,碰到該沒問題的,大多是在URL中傳輸Json等火的。尤其是用瀏覽器地址輸入的URL死活不能包含有任何特殊字符壶愤。否則會返回400 狀態(tài)碼。
首先:不推薦降低tomcat版本馏鹤,這等于掩耳盜鈴征椒,絕對得不償失。
Tomcat在 7.0.73, 8.0.39, 8.5.7 版本后湃累,在http解析時做了嚴(yán)格限制勃救。
RFC3986文檔規(guī)定,請求的Url中只允許包含英文字母(a-zA-Z)治力、數(shù)字(0-9)蒙秒、-_.~4個特殊字符以及所有保留字符。
如果要使用這些特殊字符宵统,并不是絕對不可以晕讲。Tomcat做了限制的同時,也提供了相關(guān)配置马澈。給出的解決方案第一行requestTargetAllow
瓢省,指定了允許的特殊字符,在等號后面配|{}就行了痊班。
如果你僅需要使用這三個字符勤婚,配置到此就OK了。重啟tomcat涤伐,rebuild工程再啟動馒胆,就能正常使用了缨称。
不幸的是, requestTargetAllow
只能配置|祝迂、{睦尽、} 允許這三個字符,對于其他的(例如" < > [ \ ] ^ ` { | } .)液兽,在請求時骂删,仍然攔截,如果使用了|{}之外的其他字符那怎么辦呢四啰?那就還需要如下配置宁玫。
在conf/server.xml中的<Connector>節(jié)點中,添加2個屬性:
relaxedPathChars="|{}[],"
relaxedQueryChars="|{}[],"
這2個屬性柑晒,可以接收任意特殊字符的組合欧瘪,根據(jù)需要可以自行增減。
與此相關(guān)的文檔說明:
文檔地址:https://tomcat.apache.org/tomcat-8.5-doc/config/systemprops.html
文檔地址:https://tomcat.apache.org/tomcat-8.5-doc/config/http.html
文檔地址:http://tomcat.apache.org/tomcat-7.0-doc/changelog.html
另一種方式匙赞,就是發(fā)請求前佛掖,進行URLEncoder.encode(requestURI,"UTF-8");此方法適用于 執(zhí)行發(fā)出請求的是ajax或其他客戶端程序(可以發(fā)出http請求的編程語言,都有encode()相關(guān)支持)涌庭。
然后在后臺接收請求后decode()
String params = request.getParameter(PARAMS);
params = URLDecoder.decode(params,"UTF-8");