2014-10-09 3 views
6

Я работаю над приложением iOS, которое подключается к веб-API ASP.NET через службы Restful. Я хочу использовать пользовательский делегат для выполнения проверки подлинности. Но метод делегата не вызван.Метод вызова аутентификации не вызывается при использовании пользовательского делегата NSURLSession

запрос HTTP записывается в следующем способе в контроллере представления:

- (IBAction)test:(UIButton *)sender 
{ 
    //Get Bearer Token 
    KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc]  initWithIdentifier:@"BearerToken" accessGroup:nil]; 
    NSString *bearerToken = [keychainItem objectForKey:(__bridge id)(kSecValueData)]; 

    //Configure request 
    NSURL *url = [NSURL URLWithString:@"......"]; //Replace the .... with real IP Address 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 
    [request setHTTPMethod:@"GET"]; 
    [request setValue:[NSString stringWithFormat:@"Bearer %@", bearerToken] forHTTPHeaderField:@"Authorization"]; 

    //Configure session 
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; 

    AuthChallengeDelegate *authChallengeDel = [[AuthChallengeDelegate alloc] init]; 

    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration 
                  delegate:authChallengeDel 
                delegateQueue:nil]; 

    NSURLSessionDataTask *task = [session dataTaskWithRequest:request]; 
    [task resume]; 
} 

В классе AuthChallengeDelegate я реализовал следующий метод:

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler 
{ 
    NSLog(@"%@", response); 
} 

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, 
          NSURLCredential *credential))completionHandler 
{ 
    NSLog(@"did receive challenge method called"); 
    NSLog(@"%@", challenge.protectionSpace.authenticationMethod); 
} 

Первый метод (didReceiveResponse) вызывается, а код состояния ответа - 401 с «Www-Authenticate» = Bearer в поле заголовка. Но второй метод (didReceiveChallenge) не вызывается. Кто-нибудь здесь может дать мне представление о том, почему это не называется?

(я использую Xcode 6 и моделирования в iOS8)

Спасибо.

+1

Возможно, вам нужно реализовать делегат * задачи * для задачи/ответа, то есть [URLSession (_: task: didReceiveChallenge: completeHandler:)] (https://developer.apple.com /library/IOs/documentation/Foundation/Reference/NSURLSessionTaskDelegate_protocol/index.html#//apple_ref/occ/intfm/NSURLSessionTaskDelegate/URLSession:task:didReceiveChallenge :completionHandler :), а также делегат уровня сеанса. (Метод делегата, который вы в настоящее время реализуете, обрабатывает проблемы на уровне сеанса/сервера, версия NSURLSessionTaskDelegate обрабатывает задачи на уровне задач.) –

+0

Вы сделали эту работу? У меня такая же проблема. – Vannens

+0

Привет, Ванненс, я не работал. Но я обнаружил, что моя серверная сторона не выдала вызов. На данный момент я не уверен в стороне iOS. – Dean

ответ

-1

Try изменить делегат: authChallengeDel делегировать: само

4

Есть два разных обработчиков вызов/ответ на делегатов NSURLSession в. Первый, который вы реализуете, находится на уровне сеанса и в основном обрабатывает аутентификацию на уровне сервера. От the documentation:

  • Для задач-NSURLAuthenticationMethodNTLM, NSURLAuthenticationMethodNegotiate, NSURLAuthenticationMethodClientCertificate или NSURLAuthenticationMethodServerTrust-на NSURLSession сессии на уровне объекта вызывает URLSession сессионного делегата: didReceiveChallenge: completionHandler: метод. Если ваше приложение не предоставляет метод делегирования сеанса, объект NSURLSession вызывает задачу URL-адреса делегата задачи: task: didReceiveChallenge: completeHandler: метод для обработки вызова.

  • Для задач, не связанных с сеансом (все остальные), объект NSURLSession вызывает URL-адрес делегата сеанса: task: didReceiveChallenge: completeHandler: метод для обработки вызова. Если ваше приложение предоставляет делегат сеанса, и вам необходимо обработать аутентификацию, вы должны либо обработать аутентификацию на уровне задачи, либо предоставить обработчик на уровне задач, который явно вызовет обработчик для каждого сеанса. URL-адрес делегата сессии: didReceiveChallenge: completeHandler: метод не вызывается для задач, не связанных с сеансом.

Таким образом, вы, вероятно, хотите обрабатывать проверки подлинности на уровне задач, добавив поддержку протокола для NSURLSession Task делегатом в вашем объекте делегата, и поставлять обработчик на уровне задач, т.е. URLSession(_:task:didReceiveChallenge:completionHandler:).

+1

Hi Matt. Спасибо за предложение. Я пробовал метод несеансового уровня, и он также не называется. – Dean

+0

Начиная с iOS 8.1 У меня такая же проблема. Я заметил, что вызов происходит в iOS 7.1. –

+0

Я должен добавить, что моя проблема связана с TLS-аутентификацией, для которой не требуется упомянутый выше заголовок. –

8

От iOS developer library

Важно: системные классы URL загрузки не называйте своих делегатов для обработки запросов на вызовы, если ответ сервера не содержит заголовка WWW-Authenticate.

откуда мы понимаем, что didReceiveChallenge методы должны называться НО причем способ URLSession:task:didReceiveChallenge:completionHandler: вызывается только тогда, когда заголовок выглядит 'WWW-Authenticate':'Basic'

Я не нашел решение, как обрабатывать проверки подлинности маркеров на основе где заголовок 'WWW-Authenticate':'Bearer' как в вопросе, используя проблемы аутентификации.

2

Я знаю, что эта проблема связана с iOS 8, но если вы используете iOS 9, пожалуйста, помните также, что ключ NSAppTransportSecurity в вашем Info.plist теперь является обязательным для таргетинга на любые определенные доменные имена.

У меня была такая же проблема, и я использовал wirehark для просмотра сетевого уровня TLS, чтобы проверить, какая версия TLS использовалась сервером изображений, на который я нацелился.

Основываясь на том, что вы можете добавить к вашим Info.plist и что может надеяться решить эту проблему

<key>NSAppTransportSecurity</key> 
<dict> 
    <key>NSExceptionDomains</key> 
    <dict> 
    <key>yourdomain.com</key> 
    <dict> 
     <key>NSIncludesSubdomains</key> 
     <true/> 
     <key>NSExceptionRequiresForwardSecrecy</key> 
     <false/> 
     <key>NSTemporaryExceptionMinimumTLSVersion</key> 
     <string>TLSv1.0</string> 
    </dict> 
    </dict> 
</dict> 
2

если Вы пишете:

AuthChallengeDelegate *authChallengeDel = [[AuthChallengeDelegate alloc] init]; 

authChallengeDel является LOCAL так будут выпущены как только вы выхода. Итак, сделайте это свойство

Смежные вопросы