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

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

Ошибка домена = NSURLErrorDomain Code = -1200 "Произошла ошибка SSL и безопасное соединение с сервером не может быть выполнено.

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

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

Использование Alamofire Library


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 issue


Мой файл 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

Кто-нибудь может предложить мне, почему я не могу получить эту работу после огромных усилий?

Ответ 1

Я предполагаю, что сервер, который вы пытаетесь подключить, имеет недопустимые сертификаты или не соответствует стандарту iOS 9 для ECC, Ciphers и т.д.

  • Если вы используете высокоуровневые сетевые интерфейсы API-NSURLSession, NSURLConnection или что-то еще, накладываемое поверх них, вы не имеете прямого контроля над наборами cypher, предлагаемыми клиентом. Эти API выбирают набор наборов cypher, используя собственную внутреннюю логику.

  • Если вы используете сетевые интерфейсы нижнего уровня - CFSocketStream, через свои API-интерфейсы NSStream и CFStream и все, что ниже этого, вы можете явно выбрать набор наборов cypher, которые вы хотите использовать. Как вы это делаете, зависит от конкретного API.

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

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

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

  • получить контекст Secure Transport с помощью свойства 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)
        }
    }

сообщите мне, если это поможет. Спасибо!

Ответ 2

В командной строке в OS X запустите следующее:

nscurl --ats-diagnostics https://filename.hostname.net --verbose

Это скажет вам, какие комбинации параметров ATS будут и не позволят iOS получить доступ к вашему сайту и указать на то, что не так с вашим сайтом.

Это может быть один или несколько из следующих

  • Алгоритм хеширования сертификата (должен быть SHA-256 или выше)
  • Версия TLS (должна быть 1,2)
  • Алгоритмы TLS (должны обеспечивать безопасную переадресацию)

Ответ 3

Apple выпустила полный список требований для безопасности приложений на транспорте.

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

Здесь полный контрольный список:

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

Ответ 4

У меня был такой же сценарий и застрял в течение дня. Попробуйте использовать свои мобильные данные, если это хорошо работает с вашим API, а затем проблема с сетевым брандмауэром. затем включите SSL/TLS из настроек брандмауэра.