更新された質問の更新を参照してください
アプリのサービス呼び出しに を使用していAFNetworking
ます。AFHTTPClient
私のサーバーは HTTP ダイジェスト認証を使用して認証します。WWW-Authenticate
サービス呼び出しは、次のようなチャレンジとして、応答にヘッダーを含む 401 HTTP エラーを返しています。
HTTP/1.1 401
WWW-Authenticate: Digest realm="user@myserver.com",
qop="auth",
nonce="059c37d0e654fdba9c606f35ce84741998"
Content-Type: text/html; charset=utf-8
connection:didReceiveAuthenticationChallenge:
メソッドは で呼び出されることはありません。AFURLConnectionOperation
これは、NSURLConnectionDelegate
この状況では であり、 で設定されたブロックを呼び出しますsetAuthenticationChallengeBlock:
。代わりにError Expected status code in (200-299), got 401
、AFHTTPRequestOperation
失敗ブロックでエラーが発生するだけです。
私の知る限り、WWW-Authenticate
HTTP ダイジェスト認証のヘッダーで必須のフィールドはこれらだけです。これは、ウィキペディアのこの例の応答と非常によく似ています。とにかくユーザーに HTML を表示していないため、応答の実際の本文はありません。これは重要ですか?私は不透明なフィールドを使用していませんが、これはオプションである必要があります。「auth-int」の保護品質はサポートしていません。それ以外は、Server
またはDate
ヘッダーを返しません。これらのいずれかが必要ですか?
ここで私が間違っているのは何ですか?
更新:現在、クライアント側で応答ヘッダーをログに記録しています (Apple は、私が知っているプレーン テキストの応答を単純に出力するための適切な方法を提供していません)。上記の応答は、サーバーに記録されているとおりです。の結果NSHTTPURLResponse
allHeaders
は次のとおりです。
{
"Alternate-Protocol" = "80:quic";
"Cache-Control" = private;
"Content-Type" = "text/html; charset=utf-8";
Date = "Mon, 09 Sep 2013 20:24:00 GMT";
Server = "Google Frontend";
"Transfer-Encoding" = Identity;
Vary = "Accept-Encoding";
"Www-Authenticate" = "Digest realm=\"user@myserver.com\",__ qop=\"auth\",__ nonce=\"f36dc1b8abc342d5c1cbad22a533d3868c\"";
}
Server
およびDate
ヘッダーは、実際にはサーバーに含まれており、他のいくつかのヘッダーも含まれています。サーバーは Google App Engine です。
しかし、問題は、私の\r\n
CR+LF が__
何らかの理由で変換され、ヘッダー構文が台無しになっていることです。その理由を調べてみると…
更新 2:のみを使用する\n
と、_
. HTTP 要件は、ヘッダー内の行を分割するために CR+LF+SPACE を使用することです。HttpServletResponse
それで、私の質問は、正しくエンコードされるように、この CR+LF+SPACE をヘッダー文字列に適切に含めるにはどうすればよいですか? サーバー応答プロセスのどこでエンコーディングが変更され、その結果、_
文字が取得されますか?
これは、応答を作成しているサーバー コードです。
public static void sendUnauthorizedResponse(HttpServletResponse resp, String realm, boolean isStale) throws IOException {
String s = ",\r\n ";
String header = "Digest realm=\"" + realm + "\"" + s + "qop=\"auth\"" + s + "nonce=\"" + createNonce() + "\"";
if (isStale) {
header += s + "stale=TRUE";
}
resp.setHeader("WWW-Authenticate", header);
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
log.info("Sent 401 Unauthorized Response:\n" + resp.toString());
}
最後の行は、最初に示したように応答を記録するもので、この時点で正しくフォーマットされています。
キャリッジ リターン\r
0x0D とライン フィード\n
0x0A の両方が ASCII アンダースコア_
0x5F に変更されています。
更新 3:これはクライアントの問題ではなく、Google App Engine サーバーが原因であることが確認できました。サービス コールをポスター ツールに投稿すると、同じ結果が得られます。
更新 4: CR+LF 文字を削除し、カンマ区切りの属性をすべて 1 行に含めるとうまくいくようですが、 RFC 2047によれば、行の長さは 75 文字を超えないようにする必要があります。
「エンコードされた単語」は、「charset」、「encoding」、「encoded-text」、および区切り文字を含め、75 文字を超えてはなりません。75 文字の「エンコードされた単語」に収まるよりも多くのテキストをエンコードすることが望ましい場合は、複数の「エンコードされた単語 (CRLF SPACE で区切られた)」を使用できます。
複数行のヘッダー フィールドの長さに制限はありませんが、1 つ以上の「エンコードされた単語」を含むヘッダー フィールドの各行は 76 文字に制限されています。
したがって、CR + LF 文字をヘッダー文字列に正しく配置する方法を理解する必要があります。
更新 5:したがって、HTTP ヘッダーの行ごとに許可される最大文字数はサーバーに依存し、ヘッダーには十分な数千バイトの範囲にある可能性が高いWWW-Authenticate
ようです。しかし、これは、ヘッダー文字列の「\r\n」文字が「__」に変換される理由についての質問にはまだ答えていません。これは Google App Engine のバグですか? CR+LF+SPACE を使用して、HTTP 応答の新しい行でヘッダー属性を分離したのは私だけだとは想像しがたいです。