iOS 9.3: произошла ошибка SSL и невозможно установить безопасное соединение с сервером
Я получаю следующую ошибку с самозаверяющим сертификатом
Error Domain=NSURLErrorDomain Code=-1200 "Произошла ошибка SSL, и безопасное соединение с сервером невозможно.
во время тестирования веб-сервисов для одного из моих демонстрационных приложений с
- iOS 9.3
- XCode 7.3
- Swift 2.2
- Alamofire 3.3.0
- и локальный сервер: https://filename.hostname.net/
Примечание: прежде чем предположить его дубликат, я бы попросил прочитать его полностью, даже если я сообщил об этом на форумах разработчиков Apple.
Использование библиотеки Alamofire
func testAlamofireGETRequest() -> Void
{
Alamofire.request(.GET, "https://filename.hostname.net/HelloWeb/service/greeting/john")
.responseJSON
{ response in
print("Response JSON: \(response.result.value)")
}
}
Использование NSURLSession
func testNSURLSessionRequest() -> Void {
let session = NSURLSession.sharedSession()
let urlString = "https://filename.hostname.net/HelloWeb/service/greeting/john"
let url = NSURL(string: urlString)
let request = NSURLRequest(URL: url!)
let dataTask = session.dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
print("done, error: \(error)")
//Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made.
}
dataTask.resume()
}
Я провел 2 дня без удачи:(
есть куча вопросов, уже опубликованных, но у меня ничего не получилось
- Служба безопасности транспорта заблокировала открытый текст HTTP
- iOS9 получает ошибку "произошла ошибка ssl, и невозможно установить безопасное соединение с сервером"
- Как загрузить URL-адрес HTTP с включенной App Transport Security в iOS 9? [дубликат]
- CFNetwork SSLHandshake не удалось iOS 9
- Как обработать "сбой SSLHandshake CFNetwork" в iOS
- Выполнение HTTPS-запроса в iOS 9 с самозаверяющим сертификатом
- Самозаверяющий сертификат ios9 и безопасность транспорта приложения
опубликовал Alamofire Git выпуск
- Ошибка "CFNetwork SSLHandshake fail (-9847)" при выполнении запроса не-SSL #538
- Самоподписанный сертификат не принят #876
- Как я могу подключить свой сервер как HTTPS с использованием самозаверяющего файла сертификата #977
Мой Info.pist файл обновляется для настроек ATS таким образом
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>filename.hostname.net</key>
<dict>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
Тем временем я могу получить ответ за
http: //filename.hostname.net
и https: //google.com
но не для https: //filename.hostname.net
Может кто-нибудь предложить мне, почему я не могу заставить это работать после огромных усилий?
4 ответа
Я предполагаю, что сервер, к которому вы пытаетесь подключиться, имеет недействительные сертификаты или не соответствует стандартам iOS 9 для ECC, шифров и т. Д.
Если вы используете высокоуровневые сетевые API-интерфейсы - NSURLSession, NSURLConnection или что-то еще поверх них - у вас нет прямого контроля над наборами шифров, предлагаемыми клиентом. Эти API выбирают набор наборов шифров, используя свою собственную внутреннюю логику.
Если вы используете низкоуровневые сетевые API-интерфейсы - CFSocketStream, через его NSStream и API-интерфейсы CFStream и что-либо еще ниже, - вы можете явно выбрать набор наборов шифров, которые вы хотите использовать. Как вы это сделаете, зависит от конкретного API.
Стандартная практика:
создать пару потоков
настроить его для TLS
получить безопасный транспортный контекст, используя свойство kCFStreamPropertySSLContext
настроить конкретные свойства в этом контексте
открыть потоки
Вы можете увидеть пример этого в примере кода TLSTool. В частности, посмотрите на класс TLSToolServer, где вы можете увидеть именно эту последовательность.
В очень коротком контексте вы хотите сконфигурировать поток таким образом, чтобы он обошел систему безопасности, однако в случае Alamofire вы можете сделать это напрямую:
func bypassAuthentication() {
let manager = Alamofire.Manager.sharedInstance
manager.delegate.sessionDidReceiveChallenge = { session, challenge in
var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
var credential: NSURLCredential?
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
disposition = NSURLSessionAuthChallengeDisposition.UseCredential
credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
} else {
if challenge.previousFailureCount > 0 {
disposition = .CancelAuthenticationChallenge
} else {
credential = manager.session.configuration.URLCredentialStorage?.defaultCredentialForProtectionSpace(challenge.protectionSpace)
if credential != nil {
disposition = .UseCredential
}
}
}
return (disposition, credential)
}
}
дайте мне знать, если это поможет. Спасибо!
В командной строке в OS X выполните следующее:
nscurl --ats-diagnostics https://filename.hostname.net --verbose
Это скажет вам, какие комбинации настроек ATS будут и не позволят iOS получить доступ к вашему сайту, и должно указать вам, что не так с вашим сайтом.
Это может быть один или несколько из следующих
- Алгоритм хэширования сертификата (должен быть SHA-256 или выше)
- Версия TLS (должна быть 1.2)
- Алгоритмы TLS (должны обеспечивать совершенную прямую секретность)
Apple выпустила полный список требований к App Transport Security.
Выяснилось, что мы работали с TLS v1.2, но пропустили некоторые другие требования.
Вот полный контрольный список:
- TLS требует как минимум версии 1.2.
- Соединительные шифры ограничены теми, которые обеспечивают прямую секретность (список шифров см. Ниже).
- Службе требуется сертификат, использующий, по крайней мере, отпечаток SHA256 с ключом RSA 2048 бит или более, либо ключ эллиптической кривой (ECC) 256 бит или более.
- Недействительные сертификаты приводят к серьезному отказу и отсутствию соединения.
- Принятые шифры:
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
У меня был такой же сценарий, и я застрял на один день. Попробуйте использовать мобильные данные. Если это нормально работает с API, проблема с сетевым брандмауэром. затем включите SSL / TLS в настройках брандмауэра.