IOS 8 нарушила SSL-соединение в моем приложении - CFNetwork SSLHandshake не удалось (-9806)
Мое приложение просто подключается к веб-серверу на домашнем устройстве и читает некоторый html.
Он отлично работает при использовании http, но теперь на iOS 8 при использовании https он не работает.
Я использую AFNetworking
v1 и переопределяю проверки SSL с помощью этих методов переопределения (да, я знаю, что в обычных обстоятельствах это не должно быть сделано и небезопасно и т.д., но это другая тема).
[self setAuthenticationChallengeBlock:^(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge) {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
}];
[self setAuthenticationAgainstProtectionSpaceBlock:^BOOL(NSURLConnection *connection, NSURLProtectionSpace *protectionSpace) {
if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) {
return YES; // Self-signed cert will be accepted
}
// If no other authentication is required, return NO for everything else
// Otherwise maybe YES for NSURLAuthenticationMethodDefault and etc.
return NO;
}];
Теперь с iOS 8 я получаю сообщение об ошибке:
Ошибка CFNetwork SSLHandshake (-9806)
Ошибка CFNetwork SSLHandshake (-9806)
Ошибка CFNetwork SSLHandshake (-9806)
NSURLConnection/CFURLConnection Ошибка загрузки HTTP (kCFStreamErrorDomainSSL, -9806)
Ошибка при подключении: Ошибка домена = NSURLErrorDomain Code = -1200 "Произошла ошибка SSL и невозможно создать безопасное соединение с сервером". UserInfo = 0x7b66c110 {NSLocalizedDescription = Произошла ошибка SSL и не удалось создать безопасное соединение с сервером. NSLocalizedRecoverySuggestion = Хотелось бы подключиться к серверу в любом случае?, _kCFStreamErrorCodeKey = -9806, NSErrorFailingURLStringKey = https://xxx.xxx.xxx.xxx:443/live.htm, _kCFStreamErrorDomainKey = 3, NSUnderlyingError = 0x7c0d8a20 "Произошла ошибка SSL и невозможно создать безопасное соединение с сервером". NSErrorFailingURLKey = https://xxx.xxx.xxx.xxx:443/Info.live.htm}
Я попытался перейти на FSNetworking, и он sometimes
работает при настройке:
- (void)connection:(NSURLConnection *)connection
willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
NSLog(@"Ignoring SSL");
SecTrustRef trust = challenge.protectionSpace.serverTrust;
NSURLCredential *cred;
cred = [NSURLCredential credentialForTrust:trust];
[challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
return;
}
}
Однако, выполняя 2 одновременных запроса, только 1 будет успешным, и один будет терпеть неудачу с аналогичной ошибкой выше. Кажется, что только 1 запрос достигает точки перекрытия SSL.
Кто-нибудь может пролить свет на это и что изменилось в iOS 8, чтобы сломать это, и как я могу это исправить?
Спасибо
Ответы
Ответ 1
Я столкнулся с такой же проблемой с iOS 8.
Сценарий:
- Звонки на наш https-сервер.
- Откройте https-URL с нашего сервера в
UIWebView
- Все будущие ошибки
NSURLConnection
с ошибкой SSLHandshake
useCredential:forAuthenticationChallenge
вызывал эту ошибку (но только после открытия страницы в https, размещенной на том же сервере), когда мы сразу вызывали методы SecTrust *.
Этот код вызвал ошибку:
[challenge.sender useCredential:urlCredential forAuthenticationChallenge:challenge];
SecTrustRef trustRef = [[challenge protectionSpace] serverTrust];
CFIndex count = SecTrustGetCertificateCount(trustRef);
Но этого не было:
SecTrustRef trustRef = [[challenge protectionSpace] serverTrust];
CFIndex count = SecTrustGetCertificateCount(trustRef);
[challenge.sender useCredential:urlCredential forAuthenticationChallenge:challenge];
Мне непонятно, почему это вызвало сбой SSLHandshake
на iOS 8, но не на iOS 7. Возможно, AFNetworking делает что-то после useCredential:forAuthenticationChallenge
, что вызывает ту же проблему.
Ответ 2
Ошибка, которую вы видите, можно найти в SecureTransport.h
. Это ошибка транспортного уровня: соединение завершилось неудачно, потому что оно было прервано.
На стороне клиента и сервера может возникнуть ряд причин. Это более вероятно, если сервер запрашивает у клиента сертификат, а клиент не предоставляет его, и в этот момент сервер решает отказаться. Если сервер запрашивает у клиента сертификат, ваш метод делегирования должен увидеть попытку аутентификации с использованием сертификата клиента в дополнение к доверенности сервера.