nsurlconnection - CFNetwork SSLHandshake ha avuto esito negativo su iOS 9




ios9 (12)

Per maggiori informazioni ste.vn/2015/06/10/…

Curiosamente, noterai che la connessione tenta di cambiare il protocollo http in https per proteggerti da errori nel codice in cui potresti aver erroneamente configurato l'URL accidentalmente. In alcuni casi, questo potrebbe effettivamente funzionare, ma è anche fonte di confusione.

Questa spedizione di un'applicazione con App Transport Security copre alcuni buoni consigli per il debug

ATS Fallimento

La maggior parte dei guasti ATS si presenterà come CFErrors con un codice nella serie -9800. Questi sono definiti nell'intestazione Security / SecureTransport.h

2015-08-23 06:34:42.700 SelfSignedServerATSTest[3792:683731] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)

CFNETWORK_DIAGNOSTICS

Impostare la variabile di ambiente CFNETWORK_DIAGNOSTICS su 1 per ottenere ulteriori informazioni sulla console sull'errore

nscurl

Lo strumento eseguirà diverse combinazioni di eccezioni ATS, provando una connessione sicura con l'host specificato in ogni configurazione ATS e riportando il risultato.

nscurl --ats-diagnostics https://example.com

qualcuno con iOS 9 beta 1 ha avuto questo problema?

Io uso NSURLConnection standard per connettermi a un webservice e non appena viene effettuata una chiamata al servizio web ottengo l'errore seguente. Al momento funziona con iOS 8.3

Possibile bug beta? qualsiasi idea o idea sarebbe fantastica! Lo conosco molto presto nello sviluppo di iOS 9

Ecco l'errore completo:

CFNetwork SSLHandshake non riuscito (-9824) NSURLSession / NSURLConnection Caricamento HTTP non riuscito (kCFStreamErrorDomainSSL, -9824)

 NSURLRequest * urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://mywebserviceurl"]];
        NSURLResponse * response = nil;
        NSError * error = nil;
        NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest
                                                  returningResponse:&response
                                                              error:&error];

Perché lo rende troppo complicato

Basta impostare iOS Development Target - 8.0

E Cmd + Maiusc + K


Nel tuo file .plist progetto aggiungi questa autorizzazione:

<key>NSAppTransportSecurity</key>
<dict>
    <!--Connect to anything (this is probably BAD)-->
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

Dopo due giorni di tentativi e fallimenti, ciò che ha funzionato per me è questo codice di womble

con Un cambiamento, secondo questo post dovremmo smettere di usare sottochiavi associati al dizionario NSExceptionDomains di quel tipo di Convenzione

  NSTemporaryExceptionMinimumTLSVersion

E usare alla nuova Convention

  NSExceptionMinimumTLSVersion

anziché.

documentazione della mela

il mio codice

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>YOUR_HOST.COM</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSExceptionMinimumTLSVersion</key>
                <string>TLSv1.0</string>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
    </dict>

Un altro utile strumento è nmap (brew install nmap)

nmap --script ssl-enum-ciphers -p 443 google.com

Fornisce output

Starting Nmap 7.12 ( https://nmap.org ) at 2016-08-11 17:25 IDT
Nmap scan report for google.com (172.217.23.46)
Host is up (0.061s latency).
Other addresses for google.com (not scanned): 2a00:1450:4009:80a::200e
PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers: 
|   TLSv1.0: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.1: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: server
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|     compressors: 
|       NULL
|     cipher preference: client
|_  least strength: C

Nmap done: 1 IP address (1 host up) scanned in 5.48 seconds

info.plist come di seguito o copia e incolla per me fino a iOS 9.2

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>NSAppTransportSecurity</key>
        <dict>
            <key>NSAllowsArbitraryLoads</key>
            <true/>
        </dict>

    <key>CFBundleDevelopmentRegion</key>
    <string>en</string>
    <key>CFBundleExecutable</key>
    <string>$(EXECUTABLE_NAME)</string>
    <key>CFBundleIdentifier</key>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>$(PRODUCT_NAME)</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleVersion</key>
    <string>1.0</string>
    <key>LSRequiresIPhoneOS</key>
    <true/>
    <key>UILaunchStoryboardName</key>
    <string>LaunchScreen</string>
    <key>UIMainStoryboardFile</key>
    <string>Main</string>
    <key>UIRequiredDeviceCapabilities</key>
    <array>
        <string>armv7</string>
    </array>
    <key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>UISupportedInterfaceOrientations~ipad</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationPortraitUpsideDown</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
</dict>
</plist>

Se il back-end utilizza una connessione protetta, si utilizza NSURLSession

CFNetwork SSLHandshake failed (-9801)
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801)

è necessario controllare la configurazione del server in particolare per ottenere la versione ATS e il certificato SSL Informazioni:

Invece di consentire la connessione non NSExceptionAllowsInsecureHTTPLoads = YES impostando NSExceptionAllowsInsecureHTTPLoads = YES , è invece necessario consentire la protezione NSExceptionAllowsInsecureHTTPLoads = YES se il server non soddisfa il requisito minimo (v1.2) per ATS (o meglio per correggere il lato server).

Consentendo la sicurezza ridotta a un singolo server

<key>NSExceptionDomains</key>
<dict>
    <key>api.yourDomaine.com</key>
    <dict>
        <key>NSExceptionMinimumTLSVersion</key>
        <string>TLSv1.0</string>
        <key>NSExceptionRequiresForwardSecrecy</key>
        <false/>
    </dict>
</dict>

usa il client openssl per esaminare il certificato e ottenere la configurazione del tuo server usando il client openssl:

openssl s_client  -connect api.yourDomaine.com:port //(you may need to specify port or  to try with https://... or www.)

... alla fine

SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES256-SHA
    Session-ID: //
    Session-ID-ctx: 
    Master-Key: //
    Key-Arg   : None
    Start Time: 1449693038
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)

App Transport Security (ATS) richiede il protocollo Transport Layer Security (TLS) versione 1.2.

Requisiti per la connessione mediante ATS:

I requisiti per una connessione del servizio Web per utilizzare App Transport Security (ATS) coinvolgono il server, le crittografie di connessione e i certificati, come segue:

I certificati devono essere firmati con uno dei seguenti tipi di chiavi:

  • Chiave Secure Hash Algorithm 2 (SHA-2) con una lunghezza digest di almeno 256 (ovvero SHA-256 o superiore)
  • Chiave ECL (Elliptic-Curve Cryptography) con una dimensione di almeno 256 bit

  • Chiave Rivest-Shamir-Adleman (RSA) con una lunghezza di almeno 2048 bit Un certificato non valido genera un errore grave e nessuna connessione.

I seguenti codici di connessione supportano la segretezza inoltrata (FS) e funzionano con ATS:

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

Aggiornamento: si scopre che openssl fornisce solo la versione minima del protocollo Protocollo: links TLSv1


iOS 9 e OSX 10.11 richiedono SSL TLSv1.2 per tutti gli host che si prevede di richiedere dati a meno che non si specifichi domini di eccezione nel file Info.plist dell'app.

La sintassi per la configurazione di Info.plist assomiglia a questa:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>yourserver.com</key>
    <dict>
      <!--Include to allow subdomains-->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!--Include to allow insecure HTTP requests-->
      <key>NSExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!--Include to specify minimum TLS version-->
      <key>NSExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>

Se l'applicazione (ad esempio un browser Web di terze parti) deve connettersi a host arbitrari, è possibile configurarla in questo modo:

<key>NSAppTransportSecurity</key>
<dict>
    <!--Connect to anything (this is probably BAD)-->
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

Se devi farlo, probabilmente è meglio aggiornare i tuoi server per utilizzare TLSv1.2 e SSL, se non lo stanno già facendo. Questo dovrebbe essere considerato una soluzione temporanea.

Ad oggi, la documentazione prerelease non menziona nessuna di queste opzioni di configurazione in alcun modo specifico. Una volta fatto, aggiornerò la risposta per collegarmi alla documentazione pertinente.


** NOTA IMPORTANTE PER iOS 10 BETA: **

In iOS 10, la stringa TLS DEVE essere nella forma "TLSv1.0". Non può essere solo "1.0". Sì, questo è incredibilmente stupido e rompente le app. Benvenuti nello sviluppo di iOS.

La seguente combinazione dei consigli di cui sopra funziona.

Supponiamo che tu stia cercando di connettersi a un host (YOUR_HOST.COM) con TLS 1.0.

Aggiungi questi a Info.plist della tua app

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>YOUR_HOST.COM</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.0</string>
            <key>NSTemporaryExceptionRequiresForwardSecrecy</key>
            <false/>
        </dict>
    </dict>
</dict>

Questo errore si presentava nei log a volte quando stavo usando una versione per iOS di Cordova buggy / crashy. È andato via quando ho aggiornato o abbassato cordova iOS.

Il server a cui mi stavo connettendo stava usando SSL TLSv1.2 quindi sapevo che non era questo il problema.


Il dispositivo che ho provato ha avuto un orario errato. Quindi, quando ho provato ad accedere a una pagina con un certificato che sarebbe scaduto presto, avrebbe negato l'accesso perché il dispositivo era scaduto. Per risolvere il problema, imposta il tempo corretto sul dispositivo!


Versione rapida , confronto di date e ignorando il loro tempo.

let dateExam1:NSDate = NSDate.init(timeIntervalSinceNow: 300)
let dateExam2:NSDate = NSDate.init(timeIntervalSinceNow: 10000)

let currCalendar = NSCalendar.currentCalendar()

let dateCompanent1:NSDateComponents = currCalendar.components([.Year,.Month,.Day], fromDate: dateExam1)
let dateCompanent2:NSDateComponents = currCalendar.components([.Year,.Month,.Day], fromDate: dateExam2)

let date1WithoutTime:NSDate? = currCalendar .dateFromComponents(dateCompanent1)
let date2WithoutTime:NSDate? = currCalendar .dateFromComponents(dateCompanent2)
if (date1WithoutTime != nil) && (date2WithoutTime != nil)
{
    let dateCompResult:NSComparisonResult = date1WithoutTime!.compare(date2WithoutTime!)
    if (dateCompResult == NSComparisonResult.OrderedSame)
    {
        print("Same Dates")
    }
    else
    {
        print("Different Dates")
    }
}




ios ssl nsurlconnection ios9