2015-08-26 32 views
7

我的应用程序使用NSURLConnection与服务器进行通信。我们使用https进行通信。为了处理来自所有请求的身份验证,我使用了NSURLProtocol,并在该类的代理中处理身份验证。现在我决定使用NSURLSession而不是NSURLConnection。我想做得到NSURLProtocolNSURLSession 工作,我创建了一个任务,并通过使用NSURLProtocol与NSURLSession

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 

启动加载使用NSURLProtocol被调用,也验证挑战完成后立即调用停止加载。

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

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

我在想什么?我的问题是

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

  2. 为什么使用URLSession的NSURLProtocol(相同的URL和逻辑与URL一起工作)以及如何获得NSURLProtocol与URLSession一起工作?

请帮助我,让我知道如果你想的更多细节。

回答

0

我知道这是旧的,但你所遇到的问题是在你的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) 

这些都是雨燕2.0,但应该很好地转换成的OBJ-C。

0

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

我不知道URL请求得到复制,在这种情况下,您的自定义标签可能无法正常工作,你可能会看到无限递归,直到遇到了一些内部限制。您是否尝试设置请求标头?

2

注册与NSUrlsession定制NSURLProtocol是一样的,你与NSURLConnection的做的方式。

NSURLSession阿比的(NSURLSessionDataTask和其他任务类)自定义使用时NSUrlProtocol未能妥善处理HTTP认证的挑战。 这是按预期工作在iOS 7.x和iOS中被打破8.x.Raised一个苹果雷达和我的雷达被关闭并称这是另一种雷达的副本,我仍然看到原来的雷达仍然是开放的。所以我相信这个问题到今天还没有被苹果所固定。

希望我不是太晚的答案:)

+0

任何人都知道这是固定在iOS 9.x或10.x? – Locksleyu

+0

我的雷达目前的状态仍然是开放的,所以我相信它还没有在iOS 10.x中修复。 – Chandra