5

私はこの問題で頭を壁にぶつけてきました。同様の投稿や記事を読みました。ほとんどの人は、Tomcat の server.xml ファイルで URIEncoding を UTF-8 に設定することを提案していますが、ここでは違いがないようです。

Tomcat 7 でホストされているテスト環境にデプロイされた ReSTful Web サービスがあります。Tomcat は Java 6 を使用するように構成されていますが、マシンには Java 7 もインストールされています。そこでホストされているサービスに対して基本認証テストを実行すると、ログインに失敗し、元の資格情報に Unicode 文字が含まれていると HTTP ステータス 401 の応答を受け取ります。資格情報に ASCII のみが含まれている場合、基本認証は正常に機能します。基本認証をまったく使用せずにログインすることもできます-私のサービスはカスタムログインヘッダーとRFC 2047をサポートしています。そのアプローチを使用すると、資格情報にUnicodeが含まれているかどうかは関係なく、ログインは問題になりません.

具体的には、「問題」は、ユーザー名が UTF-8 で 2 回エンコードされていることです。ログ ファイルが ANSI エンコードされているロガー (別の問題) にバグがあります。ログ ファイルを UTF-8 に変換すると、文字が正しく表示されます。しかし、この場合、問題のあるユーザー名は必要以上に長く、ファイルが UTF-8 に変換されると、(変換される前に) 本来あるべきように見えます。例えば:

  • 悪い (BASIC AUTH): SampleUser-â¢ð£Ž´ê龱</li>
  • 良い (RFC 2047): SampleUser-¢𣎴ê龱 -> SampleUser-¢ê龱</li>

ここでの本当のキッカーは、Tomcat 7 (Java 6) の独自のインスタンスをローカルで実行していて、それに対して問題を再現できないことです。2 つの Tomcat の conf ディレクトリを比較したところ、同じように見えます。基本認証が一方の環境で機能し、他方の環境では機能しない理由がわかりません。私は自分のマシンからテストを実行しているので、テスト方法(JUnit/JSystem)の不一致によるものではありません。

私が知っていることは次のとおりです。

  • 特権に関して話しているユーザーの種類は関係ありません。ユーザー名の Unicode が問題の要因です。
  • リクエストが XML 経由で送信されるか JSON 経由で送信されるかは問題ではありません。私のサービスは、両方のタイプのシリアル化をサポートしています。
  • Accept charset と content-type (該当する場合) は両方とも、リクエストで UTF-8 に設定されます。
  • Java システム プロパティは、両方の環境で同じです。

次の記事は、RFC 2047 と基本認証を組み合わせる可能性を示唆しているため、私にとって非常に興味深いものです。基本的な認証文字列自体には ASCII しか含まれていないため (base-64 でエンコードされているため)、これが必要になるとは思いませんでした。そうだとしても、ある Tomcat サーバーでそのようなことが必要で、別のサーバーでは必要ないのはなぜですか? この組み合わせアプローチを追求することは、根本的な問題に対処していないように感じます。

試すことや再確認することについての提案を前もって感謝します。テスト環境は私に限られています - 私は時間外に「それで遊ぶ」ことしかできません.

4

1 に答える 1

4

あなたが提供したデータから、実際にはUTF-8データが二重にUTF-8でエンコードされるのではなく、ASCIIエンコーディングに変換されているようです。

実際の問題に関しては、残念ながら基本認証では、デコードされていないユーザー名とパスワードの文字セットを送信する方法はありません。このため、主なオプションは、文字セットを想定して手動で指定するか、環境のデフォルトの文字セットを使用するか、文字セットを提供する独自の方法 (別のヘッダーなど) を決定することです。各オプションの種類は、環境および通信のクライアント/サーバー側をどの程度制御できるか、およびすべての呼び出しで同じ文字セットを使用するかどうかによって異なります。

1 つのサーバーが正しく動作し、もう 1 つのサーバーが正しく動作していないことに基づいて、デコードは現在、環境のデフォルトの文字セットを使用していると想定しています。エンコードされた文字列には ASCII のみが含まれていることは間違いありません (したがって、エンコードされた値を送信する際に問題が発生することはおそらくないでしょう)。そのため、デコード プロセス中 (または後) にデータが失われる可能性があります。選択しているライブラリに応じて、おそらくバイト配列または文字列のいずれかが生成されるため、バイト配列から文字列を作成するときに文字セットを提供していることを確認してください (例: new String(decodedData, someCharset)) またはそれをライブラリに提供する方法があるかどうかを確認してください (文字列を生成する場合)。

于 2013-01-09T04:33:50.247 に答える