3

次の問題があります: サーバーにリクエストを送信しています。サーバーは HTTP 基本認証を使用し、

  • 認証を送信しない場合は 401
  • 無効な認証を送信すると 401
  • 有効な認証を送信したが、そのユーザーに対してリソースが禁止されている場合は 403 。

401 を受信すると、私の NSURLSession はフレンドリーで、次の方法でデリゲートを呼び出します。

URLSession(
    session: NSURLSession,
    task: NSURLSessionTask, didReceiveChallenge
    challenge: NSURLAuthenticationChallenge,
    completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void)

ここで、サーバーに送信される資格情報を変更できます。

ただし、403 を受信すると、問題が発生します。そこから、セッションで 403 を取得するために使用したもの以外の資格情報を使用することはできません。その保護スペースのために将来送信されますか?共有された NSURLCredentialStorage を手動で空にしたり、そこに正しい認証情報を直接設定したりしても、役に立ちません。

let credential = NSURLCredential(user: username, password: password, persistence: .ForSession)
    let protectionSpace = NSURLProtectionSpace(
        host: self.host,
        port: self.apiRootURL.port!.integerValue,
        protocol: self.apiRootURL.scheme!,
        realm: "MyRealm",
        authenticationMethod: NSURLAuthenticationMethodHTTPBasic)
    NSURLCredentialStorage.sharedCredentialStorage().setDefaultCredential(credential, forProtectionSpace: protectionSpace)

この呼び出しの後、正しい資格情報だけが NSURLCredentialStorage にリストされますが、サーバーへの次の呼び出しにはまだ古い資格情報が含まれているため、必然的に別の 403 につながります。

そのメソッドを使用してセッションをリセットしてreset(completionHandler: @escaping () -> Void)も役に立ちません。

TLDR ; NSURLSession が特定の保護ドメインで成功した後も引き続き使用する資格情報を変更するにはどうすればよいですか?

4

1 に答える 1

0

403 応答メッセージをキャッチすると、次のいずれかになります。

  • ログアウト URL の要求を発行してから、ログイン URL を発行します。
  • 資格情報が資格情報ストレージに保存されないようにして、常にコールバックを取得できるようにします。
  • 403 の後に既存の資格情報を削除して、コールバックを強制します。

2 番目または 3 番目のアプローチをお勧めします。どちらの方法が平均してリクエスト数が少ないかによって異なります。持続性を避けるには、セッションの間持続するように指示する代わりに、NSURLCredentialPersistenceNone または同等の Swift を渡します。クレデンシャルを削除するには、 を呼び出しますremoveCredential:forProtectionSpace:options:

アプリの設計とサーバーの設計に応じて、他にもいくつかの可能性があります。

  • 適切な資格情報をキーチェーン/資格情報ストアに事前に追加します。警告: それを支えるキーチェーンは 1 つしかないため、異なるアカウントから複数の同時リクエストを送信する必要がある場合、これは優れたアプローチではありません。これは、特定のリクエストに対して送信される資格情報をあまり制御できないためです。
  • 別のユーザーとして認証が必要なものには、別の認証レルムを使用します。
于 2016-10-21T16:46:33.507 に答える