質問

URL の一部に '=&?/;#+%' のような文字列があると仮定します。次のように言ってみましょう。

example.com/servletPath/someOtherPath/myString/something.html?a=b&c=d#asdf

ここで、myString は上記の文字列です。重要な部分をエンコードしたので、URLは次のようになります

example.com/servletPath/someOtherPath/%3D%26%3F%2F%3B%23%2B%25/something.html?a=b&c=d#asdf

ここまでは順調ですね。

サーブレット内で次のいずれかを読み取るとき、 request.getRequestURI(), request.getRequestURL() または request.getPathInfo(), 、戻り値はすでにデコードされているため、次のような文字列が得られます

someOtherPath/=&?/;#+%/something.html?a=b&c=d#asdf

そして、実際の特殊文字とエンコードされた特殊文字を区別できません。

上記の文字を完全に禁止することで特定の問題を解決しました。これはこの状況でも機能しますが、サーブレットクラスでデコードされていないURLを取得する方法はあるのだろうか。

さらに別の編集:昨夜この問題に遭遇したとき、私は本当に何が起こっているのか気づくことができませんでした。 さらに奇妙な! サーブレットを /servletPath/* にマッピングしました。その後、必要なものを何でも配置し、パスの残りの部分に応じてサーブレットを応答させることができます。 を除外する パスに %2F がある場合。その場合 リクエストがサーブレットにヒットすることはありません, 、すると404が出ます!%2F の代わりに '/' を入力すると正常に動作します。Linux 上の Java 1.6.0-04 で Tomcat 6.0.14 を実行しています。

役に立ちましたか?

解決

ブラウザーとサーバーの両方で、「%2F」と「/」の間には根本的な違いがあります。

HttpServletRequest 仕様には次のように書かれています (ロジックはありませんが、私の知る限り)。

  • getContextPath:デコードされていない
  • パス情報の取得:デコードされた
  • getPathTranslated:デコードされていない
  • getQueryString:デコードされていない
  • getRequestURI:デコードされていない
  • getServletPath:デコードされた

getPathInfo() の結果 すべき デコードされるが、getRequestURI() の結果 してはなりません デコードされる。そうである場合、サーブレット コンテナは仕様に違反しています (Wouter Coekaerts と Francois Gravel が正しく指摘しているように)。Tomcat のどのバージョンを実行していますか?

さらに混乱を招くのは、現在の Tomcat バージョンでは、特定の特殊文字のエンコーディングを含むパスが拒否されることです。 セキュリティ上の理由から.

他のヒント

あるなら %2F の中に デコードされた URL、つまり、 エンコードされた URLが含まれています %252F.

以来 %2F/ なぜ分割しないのですか "\/" URL エンコードについて心配する必要はありませんか?

による Javadoc, 、getRequestURI は文字列をデコードしないでください。一方、getServletPath はデコードされた文字列を返します。Jetty を使用してこれをローカルでテストしたところ、ドキュメントの説明どおりに動作しました。

したがって、あなたが説明している動作はSunのドキュメントと一致しないため、あなたの状況では何か他のことが関係している可能性があります。

何かRESTy(Jerseyを使用)をしようとしているようです。URL の先頭と末尾の部分を解析するだけで、探しているデータを取得できますか?

url.substring(startLength, url.length - endLength);

アップデート: この回答は元々、パス内の '/' と '%2F' は常に同じように扱われるべきであると誤って述べていました。パスは / で区切られたセグメントのリストであるため、実際には異なります。

エンコードされた文字とエンコードされていない文字を区別する必要はありません。 パス部分 URLの。パス内には、URL 内で特別な意味を持つ文字はありません。例えば。「%2F」は「/」と同じように解釈される必要があり、そのような URL にアクセスするブラウザは、必要に応じて自由に一方を他方に置き換えることができます。両者に違いをもたらすことは、URL のエンコード方法の標準を破ることになります。

完全な URL では、次のようなさまざまな理由から、エスケープ文字と非エスケープ文字を区別する必要があります。

  • パス部分がどこで終わるかを確認します。だって?パス内にエンコードされたものを終わりとして見るべきではありません。
  • クエリ文字列内。パラメータの値の一部に「&」または「=」が含まれる可能性があるため、...
  • パス内では、「/」で 2 つのセグメントが区切られますが、「%2F」はセグメント内に含めることができます

Java は最初の 2 つのケースを適切に処理します。

  • getPathInfo() デコードされたパス部分のみを返します
  • getParameter(String) クエリ部分の一部にアクセスするには

3番目のケースではあまりうまく対処できません。2 つのパス セグメントの区切りとしての '/' と、パス セグメント (%2F) 内の '/' を区別したい場合、パスを 1 つのデコードされた文字列として一貫して表現することはできません。これは、1 つのエンコードされた文字列 (例: "foo/bar%2Fbaz") として、またはデコードされたセグメントのリスト (例: "foo"、"bar/baz") として表すことができます。しかし、getPathInfo() API はまさにそれ (デコードされた 1 つの文字列) を行うことを約束しているため、'/' と '%2F' を同じものとして扱う以外に選択肢はありません。

通常の Web アプリケーションの場合は、これで十分です。まれなケースですが、本当に違いを作る必要がある場合は、URL を独自に解析して、次のコマンドを使用して生のバージョンを取得できます。 getRequestURI(). 。それがあなたが主張しているようにデコードされたURLを提供する場合、それはあなたが使用しているサーブレット実装にバグがあることを意味します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top