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

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

ошибка домена=Nsurlerrordomain код=-1200 " произошла ошибка SSL и безопасное соединение с сервером невозможно.

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

Примечание: прежде чем предполагать его дубликат, я бы попросил прочитать его полностью, даже то же самое, что я сообщил форумам Apple dev

используя Библиотека 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 выпуск


мой информация.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, через свои API NSStream и 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 выпустила полный список требований для транспортной безопасности приложения.

оказалось, что мы работаем с TLS v1.2 но отсутствовали некоторые другие требования.

вот полный список:

  • TLS требует, по крайней мере, версия 1.2.
  • шифры соединения ограничены к тем которые обеспечивают переднюю секретность (см. ниже для списка шифров.)
  • услуги требуется сертификат, использующий по крайней мере отпечаток пальца SHA256 с битом 2048 или большим ключом RSA, или 256-битным или большим ключом эллиптической кривой (ECC).
  • недопустимые сертификаты приводят к жесткому сбою и отсутствию соединения.
  • принятые шифры: 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 из настроек брандмауэра.