ios - NSURLSession 鉴权和后台下载文件

标签 ios nsurlsession

在 iPad 应用程序中,我需要连接到服务器并在后台模式下下载使用带有 NSURLSession 对象的自签名 SSL 证书的文件:

static NSString *const URL = @"https://...";

- (void)testBackgroundDownloadTask {
    if (self.downloadTask) {
        return self;
    }
    self.session = [self backgroundSession];
    NSURL *downloadURL = [NSURL URLWithString:URL];
    NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL];
    self.downloadTask = [self.session downloadTaskWithRequest:request];
    [self.downloadTask resume];
}

- (NSURLSession *)backgroundSession{
    static NSURLSession *sess = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:URL];
        // Default configuration: working perfectly
        //NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    configuration.sessionSendsLaunchEvents = YES;
    //configuration.TLSMinimumSupportedProtocol = kSSLProtocolAll;
    configuration.networkServiceType = NSURLNetworkServiceTypeBackground;
        sess = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
    });
    return sess;
}

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
    NSURLProtectionSpace *protectionSpace = challenge.protectionSpace;
    NSString *authMethod = protectionSpace.authenticationMethod;

    if ([authMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]) {
        // obtain challenge, it working with NSURLSession in default session config 
        [self.challengeHandler handleChallenge:challenge onCompletion:^(id obj) {
            NSURLCredential *c = (NSURLCredential *)obj;
            if (c) {
                [challenge.sender useCredential:c forAuthenticationChallenge:challenge];
                completionHandler(NSURLSessionAuthChallengeUseCredential, c);
            }
            else {
                [challenge.sender cancelAuthenticationChallenge:challenge];
            }
        }];
    }
    else if ([authMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
    }
}

如果我使用defaultSessionConfiguration,我的应用在调用didReceiveChallenge 方法后成功执行下载文件(调用NSURLSesionDownloadDelegate 方法

– URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes: 
– URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: 
– URLSession:downloadTask:didFinishDownloadingToURL: 

但我使用backgroundSessionConfiguration,在调用didReceiveChallenge之后没有调用其他委托(delegate)的方法(文件没有下载和didCompleteWithError没有调用) 关于如何解决此问题的任何想法?

最佳答案

  1. 你在后台测试这个吗?

  2. 在你的 NSURLSessionDownloadDelegate 上,你应该看到你在实现时得到了什么

    - (void)URLSession:(NSURLSession *)session 
        task:(NSURLSessionTask *)task 
        didCompleteWithError:(NSError *)error
    {
        NSLog(@"%s %@ %@", __PRETTY_FUNCTION__, task.response, error);
    }    
    
  3. 如果 –URLSession:didReceiveChallenge:completionHandler: 中的任何内容是异步的,那么您需要用 UIApplication/UIBackgroundTaskIdentifier 包围它 {begin,end}BackgroundTask...,否则 iOS 将在堆栈弹出时终止您的后台进程。

关于ios - NSURLSession 鉴权和后台下载文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21545572/

相关文章:

ios - swift 2.0 : Best Practice for communication to a REST API with JSON

ios - AVAssetTrack 的 Assets 属性有时为零

iphone - 获取无效上下文错误

json - 将 NSURLSession 响应返回到其调用函数

ios - 在 iOS App 中处理大量 API 请求(不使用 Alamofire)

ios - 蜂窝网络上的 NSURLSessionConfiguration 后台任务未下载

ios - 读取 BLE 外设特性并检查其值?

android - Firebase 动态链接在自定义域中无法正常工作

ios - iOS中通过处理cookie维护Session信息

ios - 如何在 Swift 中优化链式异步请求