iPhone で HTTP ダイジェスト認証を使用する
-
21-09-2019 - |
質問
HTTP ダイジェスト認証を使用するサーバーと通信するアプリがあります。
iPhone 内の「セッション」管理は、私たち開発者にとってかなり「ブラックボックス」であるように思えます。フレームワークが http セッションをどのように処理/維持するかがわからないというのは本当ですか?
私がここでぼんやりしているだけであれば、誰かが iPhone で HTTP ダイジェスト認証を処理する方法を説明してもらえませんか?
私の基本的な実行手順は次のとおりです。
- 保護された URL にリクエストを送信する
- サーバーが 401 を送信する
- クライアントは資格情報を作成して保持し、それをサーバーに返します。
- サーバーは資格情報を検証し、検証された場合はリクエストを完了し、そうでない場合は別の 401 を送信します。
- 安全な URL に対して後続のリクエストを行う
- サーバーが再度認証を要求します....
これは単一のリクエストでは機能しますが、後続の追加リクエストを行うと、サーバーは再度承認をリクエストします。サーバーは特定のユーザーのセッションを永続化しましたが、iPhone は何らかの理由で同じセッション内でリクエストを行っていません...したがって、クライアントが保護された URL に対してリクエストを行うたびに、サーバーは認証オブジェクトを破棄し、新しい認証オブジェクトを作成する必要があります。
これは正しい行為ではないと確信しています。
この状況でブラウザがどのように動作するかを見てみると、次のようになります。
- ブラウザは安全な URL からデータをリクエストします
- サーバーは401を送信します
- ブラウザはユーザーに資格情報の入力を求め、それを保持し、サーバーに渡します
- サーバーは資格情報を検証し、検証された場合はデータを返し、検証されなかった場合は別の 401 を送信します。
- ブラウザーがセッションを管理するため、安全な URL に対して行われる後続のリクエストでは資格情報の入力は求められません。
NSURLCredential を作成し、それを NSURLCrendtialStorage 内に永続化しています。次に、アプリが「didReceiveAuthenticationChallenge」を受信すると、ストレージから資格情報を取得して返し、資格情報が存在しない場合は作成します (最初のリクエストで)。
ご協力をいただければ幸いです。ありがとう。
解決
まず最初に、HTTP セッションのことを忘れてください。HTTP セッションはダイジェスト認証のアクティブなログインとは対話しないからです (一種のセッション情報機能がありますが、それは異なります)。
実際、ダイジェストを使用する主な理由の 1 つは、ログイン状態を維持するためだけにセッションを使用する必要がないことです。セッションは重く、スケーラビリティに悪影響を及ぼします。
あなたの問題が何であるかを明確に言うことはできませんでしたが、最初に確認すべきことはわかっています。それは、古いナンスの正しい使用と正しいノンスの作成です。
ユーザー エージェントは、同じ nonce の処理を求められた場合、または後で説明する別のケース (この順序で説明する方が簡単です) を要求された場合にのみ、ユーザーに再クエリせずに認証を処理できます。
各リクエストで同じ nonce が使用されている場合、ユーザー エージェントはユーザー/パスからの「ha1」とともにそれを使用し続け、後続のリソースをリクエストします。これは先制的に行われるため、問題が発生することはありません。
もちろん、同じ nonce を使用すると、トラフィックを傍受できる人にとってリプレイ攻撃が簡単になるため、セキュリティ上の要素が生じます。Nonce は定期的に変更する必要があります。
したがって、ユーザーエージェントから無効な Authorization ヘッダーを持つリクエストを受信したが、そのリクエストが無効である理由が nonce が間違っている (期限切れのものを使用している) 場合、チャレンジに "stale=true" (デフォルトは間違い)。これにより、拒否の理由が nonce が古いことであることがユーザー エージェントに通知されます (もちろん、他の情報も間違っている可能性がありますが、どちらにしても再生させるつもりはないので、それは問題ではありません)。
このような stale=true を受け取ると、ユーザー エージェントはそれが承認されていないことを認識しますが、ユーザーに再クエリする (または UI のないコンポーネントの場合は例外をスローする) 代わりに、新しい nonce を使用して古い基準を再試行します。
これらのいずれかがあなたに影響を与えているのかどうかはわかりませんが、ナンスと古い情報がどのように決定され、通知されるかは、確かに私が最初に注目することです。
他のヒント
私はHTTP認証でiPhoneアプリを書いて、あなたが記述する何を経験しました。 (私のアプリケーションではなく、ダイジェスト認証の基本認証を使用していますが、それはここに大きな違いはありません。)
問題の原因は、iPhone側です。サーバーは、iPhoneがHTTPリクエストヘッダに認証情報を送信しない場合は401に答えるために必要とされます。そして、実際にはそれはそれは簡単に一度資格は、資格認定記憶装置に格納されている可能性がないにもかかわらずます。
この奇妙な行動はすべての要求ではなく、一方(ステータス401との最初の、200と秒)のサーバへの2つのラウンドトリップを引き起こしたので、アプリケーションの速度に重大な影響を有していた。
私は手動でHTTPリクエストヘッダに認証情報を設定することによってそれを解決しました:
NSString* credentials = [NSString stringWithFormat: @"%@:%@", usr, pwd];
const char* credentialsChars = [credentials cStringUsingEncoding: NSUTF8StringEncoding];
credentials = [CommunicationUtil stringBase64WithData: (const UInt8*) credentialsChars length: strlen(credentialsChars)];
NSString* authorizationHeader = [NSString stringWithFormat: @"Basic %@", credentials];
NSMutableURLRequest* request =
[[NSMutableURLRequest alloc] initWithURL: url
cachePolicy: NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval: 15];
[request setValue: authorizationHeader forHTTPHeaderField: @"Authorization"];
今私のアプリケーションは、非常にスムーズに動作し、非常に敏感である。
ソリューションは、ダイジェスト認証のため多少異なって見えます。しかし、あなたのアイデアを得るでしょう。