Прежде чем идти дальше, я должен начать с указания, что делать что-либо из этого - почти всегда ошибка .Вы можете получить бесплатные сертификаты TLS от различных групп, таких как LetsEncrypt .Поэтому, если у вас нет очень необычного варианта использования (например, необходимо обеспечить доверие для устройств, которые не подключены к общедоступному Интернету, общаться через локальную сеть связи), вам почти всегда лучше , а не делать какие-либооб этом, и просто установить настоящий сертификат TLS на тестовом сервере.
С учетом сказанного ....
Метод URLSession:didReceiveChallenge:completionHandler:
вызывается на делегате сеанса (если не ноль) всякий раз, когда ОС требуется запросить дополнительное подтверждение.Это может быть вызвано не для каждого запроса, но обычно так и есть.Он вызывается для каждого https-запроса, точка из-за оценки доверия к серверу.
Возможно, приведенный выше код не работает, потому что вы не запрашиваете обработку по умолчанию в тех случаях, когда пространство защиты отличается отдоверие к серверу (например, проверка подлинности прокси-сервера, базовая HTTP-аутентификация / аутентификация дайджеста и т. д.), что означает, что сетевой механизм просто сидит и ждет, когда вы скажете ему, что делать, не обращая внимания на тот факт, что переданный им блок был освобожден, когдаметод возвращен и, следовательно, никогда не будет вызван.
Вы должны делать что-то вроде этого:
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
if([challenge.protectionSpace.host isEqualToString:@"google.it"])
{
if (/* Manually verify the certificate here in some way */) {
NSURLCredential *credential = [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
} else {
// Evaluation failed. Reject the certificate.
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}
// Do not fall through for either case above.
return;
}
}
completionHandler(NSURLSes NSURLSessionAuthChallengePerformDefaultHandling, nil);
}
Кроме того, код, который вы разместили, очень небезопасен, потому что вы ничего не делаете дляподтвердить сертификат.См. Корректная проверка правильности цепочки TLS в документации для разработчиков Apple для получения дополнительной информации о том, как сделать этот шаг, но обычно вы делаете это либо с помощью
- Предоставляя копию корневого сертификата (без ключа) используется для подписи вашего поддельного сертификата, затем добавление этого корневого сертификата к набору действительных корневых сертификатов, затем повторная оценка сертификата.
- Предоставление копии открытого ключа для поддельного сертификата и утверждение, чтоон соответствует ожидаемому ключу.
При любом подходе вам, вероятно, следует вернуться к обработке по умолчанию, так что если вы когда-нибудь замените самозаверяющий сертификат реальным, он будет "просто работать".