7

私のアプリケーションはNSURLConnection、サーバーとの通信に使用します。通信には https を使用しています。すべてのリクエストからの認証を 1 か所で処理するためにNSURLProtocol、そのクラスのデリゲートで認証を使用して処理しました。NSURLSessionの代わりに使用することにしNSURLConnectionました。私は タスクを作成し、によって使用されて作業NSURLProtocolしようとしていますNSURLSessionNSURLProtocol

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 loading が呼び出され、認証チャレンジも行われますが、その直後に stop loading が呼び出されます。

しばらくするとエラーコード-999「キャンセルされました」が返ってきます。didReceiveData は呼び出されません。

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

何が欠けていますか?? 私の質問は

  1. [NSURLProtocol registerClass:[CustomHTTPSProtocol クラス]] を登録しています。NSURLConnection では問題なく動作しましたが、NSURLSession でグローバルに NSURLProtocol を登録する方法は?.

  2. URLSession を使用した NSURLProtocol (URLConnection で動作したのと同じ URL とロジック) でリクエストが失敗するのはなぜですか? また、NSURLProtocol を URLSession で動作させる方法は?.

詳細が必要な場合はお知らせください。

4

3 に答える 3

3

カスタム NSURLProtocol を NSUrlsession に登録する方法は、NSURLConnection で行う方法と同じです。

NSURLSession API (NSURLSessionDataTask およびその他のタスク クラス) をカスタム NSUrlProtocol と共に使用すると、HTTP 認証チャレンジを適切に処理できません。これは iOS 7.x では期待どおりに機能していましたが、iOS 8.x では機能しません。Apple レーダーを起動すると、別のレーダーの複製であると言ってレーダーが閉じられましたが、元のレーダーがまだ開いていることがわかります。したがって、この問題は今日の時点でアップルによってまだ修正されていないと思います。

答えが遅すぎないことを願っています:)

于 2016-03-08T08:52:07.230 に答える