Учетные данные по умолчанию NSURLCredentialStorage не используются автоматически
Я переключаюсь с NSURLConnection на NSURLSession для связи моего приложения и пока пытаюсь перейти от делегированной аутентификации к использованию NSURLCredentialStorage. Я перебрал код, однако получаю -URLSession:task:didReceiveChallenge, вызываемый делегатом, несмотря на то, что при запуске приложения он установил defaultCredentials в sharedCredentialStorage.
Защитные пространства идентичны (тот, который я создал при настройке учетных данных, и те, которые были переданы NSURLAuthenticationChallenge) в соответствии с зарегистрированными ниже сообщениями:
Register credentials for: <NSURLProtectionSpace: 0x162227c0>: Host:192.168.1.99, Server:https, Auth-Scheme:NSURLAuthenticationMethodDefault, Realm:192.168.1.99, Port:23650, Proxy:NO, Proxy-Type:(null)
Unexpected authentication challenge: <NSURLProtectionSpace: 0x1680ee40>: Host:192.168.1.99, Server:https, Auth-Scheme:NSURLAuthenticationMethodDefault, Realm:192.168.1.99, Port:23650, Proxy:NO, Proxy-Type:(null)
и во время метода делегата вызова didReceiveChallenge:(NSURLAuthenticationChallenge*):
po [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace:[challenge protectionSpace]]
результаты в
<NSURLCredential: 0x1680ff00>: thecorrectusername
/questions/11648009/mogu-li-ya-ispolzovat-nsurlcredentialstorage-dlya-bazovoj-autentifikatsii-http/11648024#11648024 указывает, что, когда сервер отвечает на вызов 401, NSURLConnection (это проблема NSURLSession?) сначала проверяет заголовки для Авторизации (там нет никакого набора) и тогда консультируется с NSURLCredentialStorage для учетных данных для пространства защиты.
Я просто не понимаю, почему у меня вызывается делегат didReceiveChallenge? Когда у меня нет установленного метода делегата, NSURLSession просто повторно отправляет запрос без каких-либо учетных данных... Я в тупике...
Редактировать: я добавил ручную обработку учетных данных в метод didReceiveChallenge: и он запускается для каждого запроса, несмотря на то, что используется только один NSURLSession.
2 ответа
У меня просто была та же проблема, когда мой URLSession не использовал сохраненные учетные данные. Затем я прочитал справочные документы для NSURLSession. По сути, это говорит о том, что если вы реализуете пользовательский делегат, то вам придется обрабатывать все сами, когда вызываются методы делегата. Другими словами, сохранение учетных данных - полдела. Вы будете получать вызов каждый раз, когда серверу требуется аутентификация, поэтому в методе didReceiveChallenge теперь вам нужно вручную извлечь учетные данные для использования и передать их обработчику завершения. Дайте мне знать, если это имеет смысл.
Вам необходимо использовать NSURLSessionTaskDelegate или NSURLSessionDelegate.
// Это для базовых учетных данных https://developer.apple.com/documentation/foundation/nsurlsessiontaskdelegate/1411595-urlsession
или же
// Это для задач на уровне сеанса - NSURLAuthenticationMethodNTLM, NSURLAuthenticationMethodNegotiate, NSURLAuthenticationMethodClientCertificate или NSURLAuthenticationMethodServerTrust https://developer.apple.com/documentation/foundation/nsurlsessiondelegate/1409308-urlsession
Например:
@interface MySessionClass : URLSession <URLSessionTaskDelegate>
@end
@implementation MySessionClass
#pragma mark - Delegate
//That method will call one time if you use NSURLCredentialPersistencePermanent but if you use other type that method it will call all the time.
- (void) URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
if (challenge.previousFailureCount == 0) {
NSURLCredential *credential = [NSURLCredential credentialWithUser:self.user password:self.password persistence:NSURLCredentialPersistencePermanent];
completionHandler(NSURLSessionAuthChallengeUseCredential, credentials);
} else {
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
}
}
@end