2015-08-26 63 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