2015-08-26 10 views
7

Meine Anwendung verwendet NSURLConnection für die Kommunikation mit dem Server. Wir verwenden https für die Kommunikation. Um die Authentifizierung von allen Anfragen an einem Ort zu behandeln, verwendete ich NSURLProtocol und behandelte die Authentifizierung in Delegaten in dieser Klasse. Jetzt habe ich mich entschieden, NSURLSession statt NSURLConnection zu verwenden. Ich versuche NSURLProtocol mit NSURLSession arbeiten tun bekommen ich eine Aufgabe erstellt und verwendet NSURLProtocol vonVerwenden von NSURLProtocol mit 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, die meine ist NSURLProtocol Klasse gefällt das loading

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 

Anfang sieht aufgerufen und auch die Authentifizierung Herausforderung ist fertig, aber das Laden wird sofort danach aufgerufen.

Fehlercode -999 "Storniert" wird nach einiger Zeit zurückgegeben. didReceiveData wird nicht aufgerufen.

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

Was bin ich ?? Meine Fragen sind

  1. Registrieren [NSURLProtocol register: [CustomHTTPSProtocol Klasse]]; funktionierte gut mit NSURLConnection, aber wie Resister für NSURLProtocol Global mit NSURLSession?.

  2. Warum werden die Anfragen in NSURLProtocol (die gleiche URL und Logik arbeitete mit URLSonnection) mit URLSession gescheitert und wie NSURLProtocol mit URLSession arbeiten?

Bitte helfen Sie mir und lassen Sie mich wissen, wenn Sie weitere Informationen wünschen.

Antwort

0

Ich weiß, das ist alt, aber das Problem, das Sie ist Methode in Ihren didReceiveChallenge hat.Sie endet das Verfahren durch

[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; 

oder

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

Aufruf Was Sie brauchen, anstatt zu tun, den Abschluss-Handler wird mit den Ergebnissen zu senden. Es würde wie folgt aussehen:

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

oder

completionHandler(.PerformDefaultHandling, nil) 

Diese sind in Swift 2.0 sollte aber schön zu Obj-C übersetzen.

0

Meine vage Erinnerung ist, dass NSURLSession automatisch alle global registrierten Protokolle verwendet. Sie sollten es also nicht erneut registrieren müssen, aber es sollte auch nicht schaden.

Ich frage mich, ob die URL-Anfrage kopiert wird, in welchem ​​Fall Ihre benutzerdefinierte Tagging möglicherweise nicht funktioniert, und Sie möglicherweise unendliche Rekursion sehen, bis es ein internes Limit erreicht. Haben Sie versucht, stattdessen einen Anforderungsheader zu setzen?

2

Das Registrieren eines benutzerdefinierten NSURLProtocols mit NSUrlsession ist mit dem von NSURLConnection identisch.

NSURLSession api (NSURLSessionDataTask und andere Aufgabenklassen), wenn sie mit benutzerdefinierten verwendet NSUrlProtocol nicht richtig HTTP-Authentifizierung Herausforderungen zu bewältigen. Dies funktionierte wie erwartet auf iOS 7.x und ist in iOS 8.x gebrochen. Eröffnet ein Apple-Radar und mein Radar wurde geschlossen, es war ein Duplikat von einem anderen Radar und ich sehe immer noch das Original-Radar ist noch offen. Also glaube ich, dass dieses Problem noch nicht von Apple festgelegt wurde.

Hoffnung Ich bin nicht zu spät mit der Antwort :)

+0

Wer weiß, ob dies in iOS 9.x oder 10.x behoben wurde? – Locksleyu

+0

Der aktuelle Status meines Radars ist noch offen, also glaube ich, dass es in iOS 10.x noch nicht behoben ist. – Chandra