Подтвердить что ты не робот

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);

}

Что еще ничего не делает.

4b9b3361

Ответ 1

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

@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

Ответ 2

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

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

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

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

  • Убедитесь, что вы правильно внедрили метод делегата 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)