2015-06-09 17 views
15

ho il seguente codice (rapida attuazione):Come faccio ad accettare un certificato SSL self-signed con iOS 7 del NSURLSession

func connection(connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: NSURLProtectionSpace) -> Bool 
{ 
    return protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust 
} 

func connection(connection: NSURLConnection, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge) 
{ 
    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust 
    { 

     if challenge.protectionSpace.host == "myDomain" 
     { 
      let credentials = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust) 
      challenge.sender.useCredential(credentials, forAuthenticationChallenge: challenge) 
     } 
    } 

    challenge.sender.continueWithoutCredentialForAuthenticationChallenge(challenge) 

} 

Funziona perfettamente in iOS 8.x, ma non funziona iOS 7 .x In iOS 7.x ho errore:

NSURLConnection/CFURLConnection HTTP carico non riuscita (kCFStreamErrorDomainSSL, -9813)

Qualche idea? grazie !!!

risposta

21

Entrambe le versioni connection:canAuthenticateAgainstProtectionSpace: e connection:didReceiveAuthenticationChallenge: sono obsolete in iOS 8, quindi è necessario utilizzare altri metodi.

Quello che sto usando nei miei progetti è un metodo delegato di NSURLSessionDelegate. Aderire a tale protocollo quindi aggiungere questo metodo:

func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential!) -> Void) { 
    completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)) 
} 

Poi, quando si utilizza l'inizializzazione NSURLSession con delega impostata su di sé. Per esempio:

var session = NSURLSession(configuration: configuration, delegate: self, delegateQueue:NSOperationQueue.mainQueue()) 

quindi utilizzare tale istanza sessione di chiamare il metodo dataTaskWithRequest on:

var task = session.dataTaskWithRequest(request){ 
    (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in 
    if error != nil { 
     callback("", error.localizedDescription) 
    } else { 
     var result = NSString(data: data, encoding: 
      NSASCIIStringEncoding)! 
    } 
} 
task.resume() 

completo esempio di lavoro può essere trovato here.

Per motivi di sicurezza, se si utilizza un certificato auto-firmato Raccomando anche attuare pinning chiave pubblica (https://gist.github.com/edwardmp/df8517aa9f1752e73353)

+0

edwardmp grazie, funziona perfettamente: D –

+0

È questo affatto sicuro senza pinning chiave pubblica? Per quanto posso vedere, non verificate che il certificato corrisponda a ciò che dovrebbe –

+0

Come potete verificare le corrispondenze del certificato quando non utilizzate la chiave pubblica? Non è richiesto il blocco della chiave, ma lo consiglio perché ho incluso il link in fondo a uno snippet. – edwardmp

0

classe eredita con URLSessionDelegate

creare un oggetto di sessione

let config = URLSessionConfiguration.default 


let session = Foundation.URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main) 


let task = session.dataTask(with: httpRequest as URLRequest, completionHandler: {requestData, response, errorData -> Void in 

      if errorData == nil { 

       dataCallback(requestData! as NSData) 
      } 
      else { 

       let error = NSError(domain: "Err-1001", code: 11, userInfo:nil) 
       failureCallback(error) 
      } 
     }); 

     task.resume() 

Add delegato methad

func urlSession(_ session: URLSession, task: URLSessionTask, didReceive  challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { 
    completionHandler(
     .useCredential, 
     URLCredential(trust: challenge.protectionSpace.serverTrust!)) 
} 

aggiungere questo nel file Info.plist

<key>NSAppTransportSecurity</key> 
<dict> 
    <key>NSExceptionDomains</key> 
    <dict> 
     <key>xyc.com</key> 
     <dict> 
      <key>NSIncludesSubdomains</key> 
      <true/> 
      <key>NSExceptionAllowsInsecureHTTPLoads</key> 
      <true/> 
      <key>NSExceptionRequiresForwardSecrecy</key> 
      <true/> 
      <key>NSExceptionMinimumTLSVersion</key> 
      <string>TLSv1.2</string> 
      <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key> 
      <false/> 
      <key>NSThirdPartyExceptionRequiresForwardSecrecy</key> 
      <true/> 
      <key>NSThirdPartyExceptionMinimumTLSVersion</key> 
      <string>TLSv1.2</string> 
      <key>NSRequiresCertificateTransparency</key> 
      <false/> 
     </dict> 
    </dict> 
</dict> 
Problemi correlati