NSURLSessionTask身份验证质询完成处理器和NSURLAuthenticationChallenge客户端 [英] NSURLSessionTask authentication challenge completionHandler and NSURLAuthenticationChallenge client

查看:272
本文介绍了NSURLSessionTask身份验证质询完成处理器和NSURLAuthenticationChallenge客户端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现自定义NSURLProtocol,并且内部希望将NSURLSession与数据任务一起用于内部联网,而不是NSURLConnection.

I am implementing a custom NSURLProtocol, and internally want to use NSURLSession with data tasks for internal networking instead of NSURLConnection.

我遇到了一个有趣的问题,想知道NSURLSession/NSURLSessionTask的质询处理程序的内部实现.

I have hit an interesting problem and wonder about the internal implementation of the challenge handler of NSURLSession/NSURLSessionTask.

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
                            didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge 
                              completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler;

这里我基本上提供了两个不同的质询处理程序,一个是completionHandler块,该处理程序提供了处理质询的所有必要信息,但是还有一个遗留的NSURLAuthenticationChallenge.client,其方法非常对应使用completionHandler信息选项一对一.

Here I am basically provided with two different challenge handlers, one being the completionHandler block, which is provided with all necessary information to handle the challenge, but there is also the legacy NSURLAuthenticationChallenge.client which has methods that correspond pretty much one to one with the completionHandler information options.

由于我正在开发协议,并且想将某些身份验证挑战传递给URL加载系统以供调用API实施,因此我需要使用NSURLSession客户端方法:

Since I am developing a protocol, and would like to pass certain authentication challenges upward the URL loading system for the calling API to implement, I need to use the NSURLSession client method:

- (void)URLProtocol:(NSURLProtocol *)protocol didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;

我的问题是completionHandlerNSURLAuthenticationChallenge.client的内部实现是否相同,如果可以,我是否可以跳过委托方法中的完成处理程序,以期望URL加载系统将调用适当的方法? NSURLAuthenticationChallenge.client方法?

My question is whether the internal implementation of the completionHandler and NSURLAuthenticationChallenge.client is the same, and if so, can I skip calling the completion handler in the delegate method, with expectance that the URL loading system will call the appropriate NSURLAuthenticationChallenge.client method?

推荐答案

要回答我自己的问题,答案是否定的.此外,Apple提供的质询发送者未实现完整的NSURLAuthenticationChallengeSender协议,因此当客户端尝试响应质询时会崩溃:

To answer my own question, the answer is no. Moreover, Apple's provided challenge sender does not implement the entire NSURLAuthenticationChallengeSender protocol, thus crashing when client attempts to respond to challenge:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFURLSessionConnection performDefaultHandlingForAuthenticationChallenge:]: unrecognized selector sent to instance 0x7ff06d958410'

我的解决方案是创建一个包装器:

My solution was to create a wrapper:

@interface CPURLSessionChallengeSender : NSObject <NSURLAuthenticationChallengeSender>

- (instancetype)initWithSessionCompletionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler;

@end

@implementation CPURLSessionChallengeSender
{
    void (^_sessionCompletionHandler)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential);
}

- (instancetype)initWithSessionCompletionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
    self = [super init];

    if(self)
    {
        _sessionCompletionHandler = [completionHandler copy];
    }

    return self;
}

- (void)useCredential:(NSURLCredential *)credential forAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    _sessionCompletionHandler(NSURLSessionAuthChallengeUseCredential, credential);
}

- (void)continueWithoutCredentialForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    _sessionCompletionHandler(NSURLSessionAuthChallengeUseCredential, nil);
}

- (void)cancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
{
    _sessionCompletionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}

- (void)performDefaultHandlingForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    _sessionCompletionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
}

- (void)rejectProtectionSpaceAndContinueWithChallenge:(NSURLAuthenticationChallenge *)challenge
{
    _sessionCompletionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
}

@end

然后使用包装好的发件人,用新对象替换挑战对象:

And I replace the challenge object with a new one, using my wrapped sender:

NSURLAuthenticationChallenge* challengeWrapper = [[NSURLAuthenticationChallenge alloc] initWithAuthenticationChallenge:challenge sender:[[CPURLSessionChallengeSender alloc] initWithSessionCompletionHandler:completionHandler]];
[self.client URLProtocol:self didReceiveAuthenticationChallenge:challengeWrapper];

这篇关于NSURLSessionTask身份验证质询完成处理器和NSURLAuthenticationChallenge客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆