2015-08-26 6 views
7

Мое приложение использует NSURLConnection для связи с сервером. Мы используем https для связи. Чтобы обрабатывать аутентификацию со всего запроса в одном месте, я использовал NSURLProtocol и обработал аутентификацию в делегатах этого класса. Теперь я решил использовать NSURLSession вместо NSURLConnection. Я пытаюсь делать получить NSURLProtocol работу с NSURLSession Я создал задачу и использовать NSURLProtocol поИспользование 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 

Start загрузка называется, а также аутентификация вызов является но прекращение загрузки вызывается сразу после этого.

Код ошибки -999 «Отменено» возвращается через некоторое время. didReceiveData не вызывается.

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

Что мне не хватает ?? Мои вопросы являются

  1. Регистрация [NSURLProtocol RegisterClass: [CustomHTTPSProtocol класс]]; работал отлично с NSURLConnection, но как Resister для NSURLProtocol глобально с NSURLSession ?.

  2. Почему запросы, полученные в NSURLProtocol (одинаковый URL-адрес и логика, работающие сURLConnection), связаны с URLSession и как заставить NSURLProtocol работать с URL-адресом?

Пожалуйста, помогите мне и дайте мне знать, если вы хотите больше детали.

ответ

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) 

Это в Swift 2.0, но должны перевести красиво Obj-C.

0

Мое смутное воспоминание о том, что NSURLSession автоматически использует любые зарегистрированные в мире протоколы. Поэтому вам не нужно будет регистрировать его снова, но это также не должно помешать сделать это.

Интересно, копируется ли URL-запрос, и в этом случае ваша пользовательская тегирование может не работать, и вы можете видеть бесконечную рекурсию, пока не достигнет некоторого внутреннего предела. Вы пытались настроить заголовок запроса вместо этого?

2

Регистрация пользовательского NSURLProtocol с NSUrlsession такая же, как и с NSURLConnection.

NSURLSession Api's (NSURLSessionDataTask и другие классы задач) при использовании с пользовательским NSUrlProtocol не справляется должным образом с задачами проверки подлинности HTTP. Это работало так, как ожидалось, на iOS 7.x и сломалось в iOS 8.x.Raised радар яблока, и мой радар был закрыт, говоря, что это дубликат другого радара, и я все еще вижу, что оригинальный радар все еще открыт. Поэтому я считаю, что эта проблема пока не установлена ​​яблоком на сегодняшний день.

Надежда Я не слишком поздно с ответом :)

+0

Кто-нибудь знает, было ли это исправлено в iOS 9.x или 10.x? – Locksleyu

+0

Текущий статус моего радара по-прежнему открыт, поэтому я считаю, что его еще не зафиксировано в iOS 10.x. – Chandra

Смежные вопросы