使用NSURLProtocol和NSURLSession

我的应用程序使用NSURLConnection与服务器通信。 我们使用https进行通信。 为了在一个地方处理来自所有请求的认证,我使用NSURLProtocol并在该类的NSURLProtocol处理认证。 现在我决定使用NSURLSession而不是NSURLConnection 。 我正在尝试获取NSURLProtocolNSURLSession NSURLProtocol工作我创建了一个任务,并使用NSURLProtocol

NSMutableURLRequest *sampleRequest = [[NSMutableURLRequest alloc]initWithURL:someURL];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.protocolClasses = @[[CustomHTTPSProtocol class]];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURLSessionDataTask *task = [session dataTaskWithRequest:checkInInfoRequest];
[task resume];

CustomHTTPSProtocol是我的NSURLProtocol类,看起来像这样

static NSString * const CustomHTTPSProtocolHandledKey = @"CustomHTTPSProtocolHandledKey";

@interface CustomHTTPSProtocol () <NSURLSessionDataDelegate,NSURLSessionTaskDelegate,NSURLSessionDelegate>

@property (nonatomic, strong) NSURLSessionDataTask *connection;
@property (nonatomic, strong) NSMutableData *mutableData;

@end

@implementation CustomHTTPSProtocol

+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
    if ([NSURLProtocol propertyForKey:CustomHTTPSProtocolHandledKey inRequest:request]) {
        return NO;
    }
    return [[[[request URL]scheme]lowercaseString]isEqualToString:@"https"];
}

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
    return request;
}

- (void) startLoading {
    NSMutableURLRequest *newRequest = [self.request mutableCopy];
    [NSURLProtocol setProperty:@YES forKey:CustomHTTPSProtocolHandledKey inRequest:newRequest];

    NSURLSession*session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
    self.connection = [session dataTaskWithRequest:newRequest];
    [self.connection resume];
    self.mutableData = [[NSMutableData alloc] init];
}

- (void) stopLoading {
    [self.connection cancel];
    self.mutableData = nil;
}

-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
    NSLog(@"challenge..%@",challenge.protectionSpace.authenticationMethod);
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
    }
    else {
        [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
    }
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
    [self.client URLProtocol:self didLoadData:data];
    NSLog(@"data ...%@  ",data); //handle data here
    [self.mutableData appendData:data];
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    if (!error) {
        [self.client URLProtocolDidFinishLoading:self];
    }
    else {
        NSLog(@"error ...%@  ",error);
        [self.client URLProtocol:self didFailWithError:error];
    }
}

@end

开始加载被调用并且认证挑战已完成,但在此之后立即调用停止加载。

错误代码-999“取消”在一段时间后返回。 didReceiveData不被调用。

Note:NSURLProtocol and the Authentication Process worked fine with NSURLConnection.

我在想什么? 我的问题是

  • 注册[NSURLProtocol registerClass:[CustomHTTPSProtocol class]]; 在NSURLConnection中运行良好,但是如何在NSURLession中全局地注册NSURLProtocol?

  • 为什么使用URLSession在NSURLProtocol(相同的URL和逻辑与URL一起工作)中请求失败,以及如何获得NSURLProtocol与URLSession一起工作?

  • 请帮助我,让我知道你是否想要更多细节。


    我知道这是旧的,但你遇到的问题是在你的didReceiveChallenge方法。 您正在通过调用来结束该方法

    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
    

    要么

    [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
    

    您需要做的是使用完成处理程序发送结果。 它看起来像这样:

    completionHandler(.UseCredential, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)
    

    要么

    completionHandler(.PerformDefaultHandling, nil)
    

    这些都在Swift 2.0中,但应该很好地转换成Obj-C。


    用NSUrlsession注册一个自定义NSURLProtocol的方式与使用NSURLConnection的方式相同。

    与自定义NSUrlProtocol一起使用时,NSURLSession Api(NS​​URLSessionDataTask和其他任务类)无法正确处理HTTP身份验证挑战。 这在iOS 7.x中按照预期工作,在iOS 8.x中打破.Raised苹果雷达,我的雷达关闭,说它是另一个雷达的副本,我仍然看到原始雷达仍然是开放的。 所以我相信这个问题到今天还没有被苹果所固定。

    希望我不晚回答:)


    我模糊的回忆是NSURLSession自动使用任何全局注册的协议。 所以你不需要重新注册它,但它也不应该伤害这样做。

    我想知道URL请求是否被复制,在这种情况下,您的自定义标记可能不起作用,并且您可能会看到无限递归,直到遇到一些内部限制。 您是否尝试设置请求标头?

    链接地址: http://www.djcxy.com/p/34871.html

    上一篇: Using NSURLProtocol with NSURLSession

    下一篇: notification launch custom method/class