2015-07-19 19 views
8

Ho sviluppato un'applicazione IOS che comunica con un server tramite HTTP (sono anche lo sviluppatore del server, incorpora un server Tomcat).Errore SSL IOS9 con NSURLSession

Questa applicazione funziona senza problemi con IOS8 ma non con IOS9.

ottengo il seguente errore durante l'invio di una richiesta HTTPS:

Session download has failed : Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo=0x7fa9c44b2e40 {NSErrorFailingURLStringKey=https://127.0.0.1:8443/MyServer/MyApp, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSErrorFailingURLKey=https://127.0.0.1:8443/MyServer/MyApp, _kCFStreamErrorCodeKey=-9802, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made.} 

Sulla base di documentazione Apple quando il codice di errore = -1200 accade è perché TLSv1.1 invece di TLSv1.2. Ho verificato con un comando openSSL e il mio server utilizza TLSv1.2.

Quando si imposta in info.plist la proprietà NSAllowsArbitraryLoads = true, l'errore scompare ma non voglio mantenerlo in questo modo.

Il mio server utilizza un certificato autofirmato, forse è la causa del problema? Di seguito è riportato il codice che sto usando per didReceiveChallenge

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { 

[RequestURLUtilities dumpChallenge:challenge]; 


if (challenge.protectionSpace != Nil) { 
    NSURLProtectionSpace *protection = challenge.protectionSpace; 

    SecTrustRef sslState = protection.serverTrust; 
    if (sslState == Nil) { 
     NSLog(@"%s Warning: empty serverTrust",__PRETTY_FUNCTION__); 
    } 


    if ([protection.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { 

     NSLog(@"%s => NSURLAuthenticationMethodServerTrust", __PRETTY_FUNCTION__); 
     // warning normaly I should check the validity of the SecTrustRef before to trust 
     NSURLCredential* credential = [NSURLCredential credentialForTrust:sslState]; 

     // Put in command for test 

     completionHandler(NSURLSessionAuthChallengeUseCredential, credential); 

    } else { 
     NSLog(@"%s => Called for another challenge", __PRETTY_FUNCTION__); 
     completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, NULL); 
    } 

} 

Devo creare il mio CA e poi i miei propri certificati? Come procedere? Che cosa manca? Qualsiasi aiuto sarà molto apprezzato.

Sebastien.

risposta

10

Dopo aver discusso con il supporto Apple, il problema è dovuto al certificato autofirmato.

ATS si fida solo del certificato firmato da una CA ben nota, tutti gli altri vengono rifiutati. Di conseguenza, l'unica soluzione con un certificato autofirmato è impostare un'eccezione con NSExceptionDomains.

+1

Questo lavoro ha funzionato? Quale eccezione dovrei inserire per il mio dominio? Ho provato praticamente tutte le combinazioni e ho ancora ricevuto il codice erroc -1200 ... Apple afferma che dovremmo aggiungere "NSExceptionAllowsInsecureHTTPLoads" e impostarlo su true in modo che il dominio sia accessibile con un errore. Ma tutto quello che sto ottenendo è un errore senza risposta. – Ivan

+0

Risolto il mio problema, nel mio caso c'era un problema con il mio dominio di prova che non aveva certificato ma utilizzato il protocollo HTTPS. Per questo l'unica soluzione è aggiungere l'eccezione NSAllowsArbitraryLoads impostata su true in Info.plist. – Ivan

5

Sfortunatamente sarà necessario ottenere un certificato da una CA importante o impostare un'eccezione che è solo una correzione temporanea. Dovresti davvero risolvere il tuo SSL e testarlo a SSL Labs

Fai clic con il tasto destro del mouse su Info.plist e seleziona Apri come codice sorgente. Il seguente codice ti consentirà di bypassare solo per il tuo server. La documentazione è here

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

È inoltre possibile impostare questo modificando l'info.plist come un elenco di proprietà. Vedi questo articolo WORKING WITH APPLE’S APP TRANSPORT SECURITY

+0

Se non si dispone di nome di dominio, allora l'unica opzione è quella di utilizzare come NSAllowsArbitraryLoads: NSAppTransportSecurity NSAllowsArbitraryLoads sebastien

Problemi correlati