Tomcat : Invalid character found in the request target


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

Tomcat的coyote-connector解析到請求中包含了不合法的字符,比如  { }  ( )  ^ ` \  | #  \\

這是典型的400錯誤,不合法的請求,根據RFC (Request Format Comment)文檔的規定,以上字符不能被用在Request Header,也就是request的URI中。

我遇到這個問題是兩個tomcat應用之間通訊時發送了一個請求,這個請求包含片段.*\.(css|js|jpg|jpeg|png|gif|ico|woff)$,

很顯然,這個請求中包含 \ ( | 這三個不合法的字符;轉義是不能解決問題的;因為tomcat會對請求中每個字符都進行檢查;

我的解決辦法就是 將 .*\.(css|js|jpg|jpeg|png|gif|ico|woff)$ 換成 .*tpl$,.*css$,.*js$,.*jpg$,.*jpeg$,.*bmp$,.*png$,.*gif$,.*ico$,.*woff$

 

 

查看tomcat源碼

apache-tomcat-7.0.73-src\java\org\apache\coyote\http11\InternalInputBuffer.java 

public class InternalInputBuffer extends AbstractInputBuffer<Socket> {
   ....省略
    /**
     * Read the request line. This function is meant to be used during the
     * HTTP request header parsing. Do NOT attempt to read the request body
     * using it.
     *
     * @throws IOException If an exception occurs during the underlying socket
     * read operations, or if the given buffer is not big enough to accommodate
     * the whole line.
     */
    @Override
    public boolean parseRequestLine(boolean useAvailableDataOnly)
        throws IOException {
    ...省略
        //
        // Reading the URI
        //
        boolean eol = false;
        while (!space) {
            // Read new bytes if needed
            if (pos >= lastValid) {
                if (!fill())
                    throw new EOFException(sm.getString("iib.eof.error"));
            }
            // Spec says single SP but it also says be tolerant of HT
            if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
                space = true;
                end = pos;
            }else if (HttpParser.isNotRequestTarget(buf[pos])) {  
        //如果請求參數中的字符不是被允許的字符,則拋異常 HttpParser這個類 看下面代碼片
throw new IllegalArgumentException(sm.getString("iib.invalidRequestTarget")); } pos++; } ... 省略 return true; } }

apache-tomcat-7.0.73-src\java\org\apache\tomcat\util\http\parser\HttpParser.java

private static final int ARRAY_SIZE = 128;
private static final boolean[] IS_NOT_REQUEST_TARGET = new boolean[ARRAY_SIZE];
static { // Digest field types.for (int i = 0; i < ARRAY_SIZE; i++) { // Control> 0-31, 127 if (i < 32 || i == 127) { IS_CONTROL[i] = true; }// Not valid for request target. // Combination of multiple rules from RFC7230 and RFC 3986. Must be // ASCII, no controls plus a few additional characters excluded        // 不合法的字符在這里都會導致請求不合法而拋異常 請求失敗 if (IS_CONTROL[i] || i > 127 || i == ' ' || i == '\"' || i == '#' || i == '<' || i == '>' || i == '\\' || i == '^' || i == '`' || i == '{' || i == '|' || i == '}') { IS_NOT_REQUEST_TARGET[i] = true; } } }

 HTTP協議只是一個OSI應用層通訊的標准,在tomcat源碼中對HTTP進行了實現,可能在一些Tomcat版本中沒有實現對請求字符的限制,可以預見,在Tomcat7.0.64之后的版本以及 Tomcat8、9都會對請求頭的字符進行限制。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM