使用NSURLSession自定义委托时不调用身份验证质询方法

Dea*_*ean 6 authentication objective-c ios nsurlsession

我正在开发一个iOS应用程序,它通过Restful服务连接到ASP.NET Web API.我想使用自定义委托来处理身份验证质询.但委托方法不会被调用.

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];
}
Run Code Online (Sandbox Code Playgroud)

在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);
}
Run Code Online (Sandbox Code Playgroud)

调用第一个方法(didReceiveResponse),响应状态代码为401,标题字段中有"Www-Authenticate"= Bearer.但是没有调用第二种方法(didReceiveChallenge).这里的任何人都可以告诉我为什么不叫它?

(我正在使用Xcode 6并在iOS8中进行模拟)

谢谢.

Art*_*hur 8

来自iOS开发人员库

要点:除非服务器响应包含WWW-Authenticate标头,否则URL加载系统类不会调用其委托来处理请求质询.

我们从中了解didReceiveChallenge应该调用方法但是URLSession:task:didReceiveChallenge:completionHandler:只有在标题看起来时才调用该方法'WWW-Authenticate':'Basic'

我还没有找到任何解决方案如何处理基于令牌的身份验证,其中标头'WWW-Authenticate':'Bearer'使用身份验证挑战.


Mat*_*son 6

NSURLSession的代表中有两个不同的质询/响应处理程序.您正在实现的第一个是会话级别,基本上处理服务器级别的身份验证.从文档:

  • 对于会话级别的挑战 - NSURLAuthenticationMethodNTLM,NSURLAuthenticationMethodNegotiate,NSURLAuthenticationMethodClientCertificate或NSURLAuthenticationMethodServerTrust,NSURLSession对象调用会话委托的URLSession:didReceiveChallenge:completionHandler:方法.如果您的应用程序未提供会话委托方法,则NSURLSession对象将调用任务委托的URLSession:task:didReceiveChallenge:completionHandler:处理质询的方法.

  • 对于非会话级别的挑战(所有其他挑战),NSURLSession对象调用会话委托的URLSession:task:didReceiveChallenge:completionHandler:处理挑战的方法.如果您的应用程序提供了会话委托,并且您需要处理身份验证,那么您必须在任务级别处理身份验证,或者提供一个显式调用每会话处理程序的任务级处理程序.会话委托的URLSession:didReceiveChallenge:completionHandler:方法不会针对非会话级别的挑战进行调用.

因此,您可能希望通过在委托对象中添加NSURLSession 任务委托的协议支持来处理任务级别身份验证,并在任务级别提供处理程序,即 URLSession(_:task:didReceiveChallenge:completionHandler:).


gab*_*ler -1

尝试将 delegate:authChallengeDel 更改为 delegate:self