NSURLSession + сервер с самозаверяющим сертификатом

у меня есть приложение, которое является производственным вместе с сервером разработки, который имеет самоподписанный сертификат.

Я пытаюсь проверить NSURLSession и фоновая загрузка, но, похоже, не может пройти - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler

когда я использую NSURLConnection Я могу обойти это, используя:

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {

    NSLog(@"canAuthenticateAgainstProtectionSpace %@", [protectionSpace authenticationMethod]);

    return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {

    NSLog(@"didReceiveAuthenticationChallenge %@ %zd", [[challenge protectionSpace] authenticationMethod], (ssize_t) [challenge previousFailureCount]);

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

но я не могу понять, как заставить это работать с NSURLSession >: (

это то, что у меня есть в настоящее время (это не работает):

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
    NSLog(@"NSURLSession did receive challenge.");

    completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}

Я также попытался создать Категорию NSURLSession это позволит любой сертификат для хоста:

#import "NSURLRequest+IgnoreSSL.h"

@implementation NSURLRequest (IgnoreSSL)

+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host {
    return YES;
}

+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host {}

@end

что также, похоже, не помогает.


редактировать

я обновил этот метод, чтобы возвратить:

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {

    //Creates credentials for logged in user (username/pass)
    NSURLCredential *cred = [[AuthController sharedController] userCredentials];

    completionHandler(NSURLSessionAuthChallengeUseCredential, cred);

}

который по-прежнему ничего не делает.

2 ответов


для меня ваш первый пример работает нормально. Я тестировал следующий код без проблем (он, конечно, очень небезопасен, поскольку он позволяет любой сертификат сервера).

@implementation SessionTest

- (void) startSession
{
    NSURL *url = [NSURL URLWithString:@"https://self-signed.server.url"];

    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];

    NSURLSessionDataTask * dataTask = [defaultSession dataTaskWithURL:url
                                                completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                    if(error == nil)
                                                    {
                                                        NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
                                                        NSLog(@"Data: %@",text);
                                                    }
                                                    else
                                                    {
                                                        NSLog(@"Error: %@", error);
                                                    }
                                                }];

    [dataTask resume];
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
    completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}

@end

обновление: это интерфейс класса, класс SessionTest является NSURLSessionDataDelegate, чтобы начать загрузку данных, вы создаете объект SessionTest и вызываете метод startSession.

@interface SessionTest : NSObject <NSURLSessionDelegate>

- (void) startSession;

@end

недостаточно информации, чтобы предложить конкретное решение вашей проблемы.

вот некоторые основные требования:

  • Так как вы хотите фоновую задачу, убедитесь, что вы создали соответствующую NSSession объект через backgroundSessionConfiguration:. Использование этого метода фабрики класса является обязательным для получения фон сессий.

  • для запросов, запущенных в фоновом режиме в отдельном процессе, только загрузить и скачать задачи поддерживаются. Обратите внимание, что в исходном коде вы используете данные задач.

  • убедитесь, что у вас есть правильно реализован метод делегата application:handleEventsForBackgroundURLSession:completionHandler: в делегате приложения. Если приложение не запущено, а сеанс выполняется в своем собственном процессе и требует учетных данных, iOS перезапустит приложение в фоновом режиме, и фоновый сеанс вызовет этот метод делегата. Смотреть также https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:handleEventsForBackgroundURLSession:completionHandler:

отключение оценки доверия сервера должно работать так, как вы пытались в первом примере. используйте это только для разработки!

Смотрите также (https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/URLLoadingSystem/Articles/UsingNSURLSession.html#//apple_ref/doc/uid/TP40013509-SW44)