Как изменить учетные данные для NSURLSession

У меня следующая проблема: я делаю запросы к серверу, который использует HTTP-аутентификацию и дает мне

  • 401, если я не отправляю аутентификацию
  • 401, если я отправлю неверную аутентификацию
  • a 403, если я отправлю действительную аутентификацию, но ресурс для этого пользователя запрещен.

Когда я получаю 401, моя NSURLSession достаточно дружелюбна, чтобы вызвать своего делегата через

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

где я могу изменить учетные данные, отправляемые на сервер.

Однако при получении 403 я сталкиваюсь с проблемой. Оттуда я не могу заставить сеанс использовать какие-либо другие учетные данные, кроме тех, что он использовал для получения 403. На 403 делегат не спрашивается (это нормально, это не 401), так как я могу контролировать, какие учетные данные отправлено в будущем для этой защиты пространства? Даже ручная очистка общего 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 продолжает использовать, как только он имел успех с ними для данного домена защиты?

1 ответ

Вы ловите ответное сообщение 403, затем либо

  • Выполните запрос URL-адреса для выхода, затем URL-адреса для входа.
  • Всегда предотвращайте сохранение учетных данных в хранилище учетных данных, чтобы вы всегда получали обратный вызов.
  • Удалите существующие учетные данные после 403, чтобы вызвать обратный вызов.

Я рекомендую второй или третий подход, в зависимости от которого в среднем получается меньше запросов. Чтобы избежать персистентности, передайте NSURLCredentialPersistenceNone или эквивалент Swift вместо того, чтобы указывать ему сохраняться в течение сеанса. Чтобы удалить учетные данные, позвоните removeCredential:forProtectionSpace:options:,

Есть несколько других возможностей, которые могут работать, в зависимости от дизайна вашего приложения и дизайна сервера:

  • Предварительно добавьте правильные учетные данные в связку ключей / хранилище учетных данных. Предостережение: есть только одна цепочка для ключей, поддерживающая его, так что это не очень хороший подход, если у вас есть несколько одновременных запросов, которые должны приходить от разных учетных записей, потому что вы не будете иметь большого контроля над тем, какие учетные данные отправляются для данного запроса.
  • Используйте другую область аутентификации для вещей, которые требуют аутентификации от имени другого пользователя.
Другие вопросы по тегам