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);
}
Что еще ничего не делает.
Ответы
Ответ 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
Не хватает информации, чтобы предложить конкретное решение вашей проблемы.
Вот некоторые основные требования:
Отключение проверки доверия сервера должно работать, как вы пробовали в первом примере. Используйте это только для разработки!
См. также (https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/URLLoadingSystem/Articles/UsingNSURLSession.html#//apple_ref/doc/uid/TP40013509-SW44)