バージョン情報:
サーバーのバージョン: Apache Tomcat/9.0.17 サーバー構築: 2019 年 3 月 13 日 15:55:27 UTC サーバー番号: 9.0.17.0 OS名:Windows8.1 OSバージョン:6.3 アーキテクチャ: amd64 JVM バージョン: 1.8.0_40-b25
スプリングブート-2.1.4 スプリングコア-5.1.6
次のような HTML ページがあります: localhost/example/37%.html (申し訳ありませんが、編集ページがリンクに自動的に変更し、% の後に 25 を追加するため、URL を http// で始めることはできません) この URL にアクセスすると、HTTP ステータス 400 というエラーが発生しました。 % はエスケープ文字であるため、そのはずです。 そこで URL を localhost/example/37%25.html に変更しました。 今回は、新しいエラーが発生しました:
ホワイトラベルのエラーページ このアプリケーションには /error の明示的なマッピングがないため、これはフォールバックとして表示されます。 2020年9月3日木 09:25:13 CST予期しないエラーが発生しました (タイプ = 内部サーバー エラー、ステータス = 500)。 URLDecoder: エスケープ (%) パターンに不正な 16 進文字が含まれています - 入力文字列の場合: ".h"
Tomcat コンソールを確認したところ、次のエラー メッセージが出力されました。
2020-09-03 09:25:12 [http-nio-8080-exec-3] ERROR
o.s.b.w.s.support.ErrorPageFilter - Forwarding to error page from request [/37%.html] due to exception [URLDecoder: Illegal hex characters in escape (%) pattern - For input string: ".h"]
java.lang.IllegalArgumentException: URLDecoder: Illegal hex characters in escape(%) pattern - For input string: ".h"
at java.net.URLDecoder.decode(URLDecoder.java:194)
at org.springframework.web.servlet.resource.PathResourceResolver.isInvalidEncodedPath(PathResourceResolver.java:285)
at org.springframework.web.servlet.resource.PathResourceResolver.isResourceUnderLocation(PathResourceResolver.java:254)
tomcat (またはブラウザ) は %25 を % にデコードしたようですが、springboot はまだ % を再度デコードしています (PathResourceResolver.java)
これがバグの問題なのか、それともスプリングブートで URL に % を許可しない正しい方法なのかわかりません。
面白いものを見つけました。
現在、2 つの Web ページがあり、1 つは 37%.html という名前で、もう 1 つは 37%25.html という名前です
springb のロジックに従います% を 2 回デコードするので、次の URL にアクセスしました。
localhost/example/37%2525.html
すると、37%.html が表示されますが、37%25.html も表示されます。
それで、スプリングブートで % をデコードする回数、または方法は何ですか ???
その後、Springboot で 2 つのクラス ファイルが見つかりました。 ResourceHttpRequestHandler.java PathResourceResolver.java
それらはすべて isInvalidEncodedPath() という名前の関数を持っています
コードはここにあります:
ResourceHttpRequestHandler.isInvalidEncodedPath(パス)
private boolean isInvalidEncodedPath(String path) {
if(path.contains("%")) {
try {
String decodedPath = URLDecoder.decode(path, "UTF-8");
if(this.isInvalidPath(decodedPath)) {
return true;
}
decodedPath = this.processPath(decodedPath);
if(this.isInvalidPath(decodedPath)) {
return true;
}
} catch (UnsupportedEncodingException | IllegalArgumentException var3) {
;
}
}
return false;
}
PathResourceResolver.isInvalidEncodedPath(resourcePath)
private boolean isInvalidEncodedPath(String resourcePath) {
if(resourcePath.contains("%")) {
try {
String decodedPath = URLDecoder.decode(resourcePath, "UTF-8");
if(decodedPath.contains("../") || decodedPath.contains("..\")) {
this.logger.warn("Resolved resource path contains encoded \"../\" or \"..\\": " + resourcePath);
return true;
}
} catch (UnsupportedEncodingException var3) {
;
}
}
return false;
}
何か違うものが見えますか??どちらも URLDecoder.decode(resourcePath, "UTF-8") を実行しますが、異なる例外をキャッチします。
URL にアクセスすると、springboot は次の順序で関数を呼び出します。
1 ResourceHttpRequestHandler.isInvalidEncodedPath(パス) 2 PathResourceResolver.isInvalidEncodedPath(resourcePath)
したがって、ResourceHttpRequestHandler.isInvalidEncodedPath(path) で /37%25.html にヒットすると、tomcat (またはブラウザ) が %25 を % にデコードするため、/37%.html が取得されます。次に URLDecoder.decode("/37%.html", "UTF-8") を実行すると、IllegalArgumentException がトリガーされ、キャッチされますが、何もせず、false を返します。 PathResourceResolver.isInvalidEncodedPath(resourcePath),URLDecoder.decode("/37%.html", "UTF-8") で、IllegalArgumentException をトリガーし、キャッチされず、例外をスローします。
ResourceHttpRequestHandler.isInvalidEncodedPath(path) で /37%2525.html にヒットすると、/37%25.html, URLDecoder.decode("/37%25.html", "UTF-8"; が取得されます。 )、問題ない。 PathResourceResolver.isInvalidEncodedPath(resourcePath)、URLDecoder.decode("/37%25.html"、"UTF-8")、これも問題ありません。その後、37%25.html を表示します。
「/37%.html」とだけ入力すると、400 エラー、無効な URI: isHexDigit が表示されます。
そのため、残念ながら % char を含む URL には正しくアクセスできません。
共有 フォローする2020 年 9 月 7 日 6:17 に回答
スティーブン01997スティーブン01997
1
1
銅バッジ 1 個
1
ああ、もう一つ興味深いことがありました。 IDEA でのデバッグに jrebel を使用している場合、エラーは表示されません。どのページも良好です。 PathResourceResolver.isInvalidEncodedPath(resourcePath) が呼び出されないためです。理由はわかりません.... (jrebel バージョン 2018.1.6)
– スティーブン019972020 年 9 月 7 日 6:28