首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSURLProtocol与NSURLSession的结合

NSURLProtocol与NSURLSession的结合
EN

Stack Overflow用户
提问于 2015-08-26 09:48:28
回答 3查看 3.4K关注 0票数 7

我的应用程序使用NSURLConnection与服务器进行通信。我们使用https进行通信。为了在一个地方处理来自所有请求的身份验证,我使用了NSURLProtocol,并在该类中处理委托中的身份验证。现在我决定使用NSURLSession而不是NSURLConnection。我正在尝试让NSURLProtocolNSURLSession一起工作--我创建了一个任务并使用了NSURLProtocol

代码语言:javascript
复制
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类,如下所示

代码语言:javascript
复制
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

启动加载被调用,身份验证挑战也被完成,但是停止加载在那之后立即被调用。

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

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

我少了什么??我的问题是

  1. 注册[NSURLProtocol寄存器类:CustomHTTPSProtocol类];在NSURLConnection中工作得很好,但是如何用NSURLSession全局地拒绝NSURLProtocol?
  2. 为什么请求在NSURLProtocol (相同的URL和逻辑工作withURLConnection)中URLSession失败,以及如何让NSURLProtocol使用URLSession?

请帮助我,如果你想要更多的细节,请告诉我。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-08-17 19:00:21

我知道这是老问题,但问题在于您的didReceiveChallenge方法。您将通过调用

代码语言:javascript
复制
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];

代码语言:javascript
复制
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];

相反,您需要做的是使用完成处理程序发送结果。看起来是这样的:

代码语言:javascript
复制
completionHandler(.UseCredential, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)

代码语言:javascript
复制
completionHandler(.PerformDefaultHandling, nil)

这些都在SWIFT2.0中,但是应该很好地翻译成Obj。

票数 0
EN

Stack Overflow用户

发布于 2016-03-08 08:52:07

使用NSURLProtocol注册自定义NSUrlsession与使用NSURLConnection的方式相同。

NSURLSession Api (NSURLSessionDataTask和其他任务类)与自定义NSUrlProtocol一起使用时,无法正确处理HTTP挑战。这在iOS 7.x上运行得如期而至,在苹果雷达iOS 8.x.Raised上也出现了故障,我的雷达关闭了,说这是另一种雷达的复制品,我仍然看到原来的雷达仍在开着。因此,我相信,到今天为止,苹果还没有解决这个问题。

希望我在回答上不会太晚:)

票数 3
EN

Stack Overflow用户

发布于 2015-10-28 19:04:54

我模糊的回忆是,NSURLSession自动使用任何全局注册的协议。因此,您不应该再次注册它,但它也不应该伤害这样做。

我想知道URL请求是否被复制,在这种情况下,您的自定义标记可能无法工作,并且您可能会看到无限递归,直到它达到某种内部限制。您是否尝试过设置请求头?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32223262

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档