iOS 9.3: произошла ошибка SSL и невозможно установить безопасное соединение с сервером

Я получаю следующую ошибку с самозаверяющим сертификатом

Error Domain=NSURLErrorDomain Code=-1200 "Произошла ошибка SSL, и безопасное соединение с сервером невозможно.

во время тестирования веб-сервисов для одного из моих демонстрационных приложений с

Примечание: прежде чем предположить его дубликат, я бы попросил прочитать его полностью, даже если я сообщил об этом на форумах разработчиков 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 дня без удачи:(

есть куча вопросов, уже опубликованных, но у меня ничего не получилось

опубликовал Alamofire Git выпуск


Мой 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.

Стандартная практика:

  1. создать пару потоков

  2. настроить его для TLS

  3. получить безопасный транспортный контекст, используя свойство kCFStreamPropertySSLContext

  4. настроить конкретные свойства в этом контексте

  5. открыть потоки

Вы можете увидеть пример этого в примере кода 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 в настройках брандмауэра.

Другие вопросы по тегам