[Ios] Come utilizzare NSURLConnection per connettersi con SSL per un certificato non attendibile?


Answers

Se non si desidera (o non è possibile) utilizzare le API private, esiste una libreria open source (licenza BSD) denominata ASIHTTPRequest che fornisce un wrapper attorno alle CFNetwork APIs livello inferiore. Di recente hanno introdotto la possibilità di consentire HTTPS connections utilizzando certificati autofirmati o non attendibili con -setValidatesSecureCertificate: API. Se non si desidera accedere all'intera libreria, è possibile utilizzare la fonte come riferimento per implementare la stessa funzionalità da soli.

Question

Ho il seguente codice semplice per connettersi a una pagina Web SSL

NSMutableURLRequest *urlRequest=[NSMutableURLRequest requestWithURL:url];
[ NSURLConnection sendSynchronousRequest: urlRequest returningResponse: nil error: &error ];

Tranne che genera un errore se il certificato è Error Domain=NSURLErrorDomain Code=-1202 UserInfo=0xd29930 "untrusted server certificate". C'è un modo per impostarlo per accettare connessioni comunque (proprio come in un browser puoi premere accept) o un modo per aggirarlo?




Ho postato un codice gist (basato sul lavoro di qualcun altro che noto) che consente di autenticare correttamente contro un certificato generato automaticamente (e come ottenere un certificato gratuito - vedere i commenti in fondo a Cocoanetics )

Il mio codice è qui github




La soluzione alternativa di categoria pubblicata da Nathan de Vries passerà i controlli API privati ​​di AppStore ed è utile nei casi in cui non si ha il controllo dell'oggetto NSUrlConnection . Un esempio è NSXMLParser che aprirà l'URL fornito dall'utente, ma non espone NSURLRequest o NSURLConnection .

In iOS 4 la soluzione sembra ancora funzionare, ma solo sul dispositivo, il simulatore non richiama più il metodo allowsAnyHTTPSCertificateForHost: .




Con AFNetworking ho consumato con successo https webservice con il codice sottostante,

NSString *aStrServerUrl = WS_URL;

// Initialize AFHTTPRequestOperationManager...
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];

[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
manager.securityPolicy.allowInvalidCertificates = YES; 
[manager POST:aStrServerUrl parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
    successBlock(operation, responseObject);

} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
    errorBlock(operation, error);
}];



Non posso prendermi alcun merito per questo, ma questo che ho trovato ha funzionato molto bene per i miei bisogni. shouldAllowSelfSignedCert è la mia variabile BOOL . Basta aggiungere al proprio delegato NSURLConnection e si dovrebbe essere rockin per un bypass rapido su base per connessione.

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)space {
     if([[space authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) {
          if(shouldAllowSelfSignedCert) {
               return YES; // Self-signed cert will be accepted
          } else {
               return NO;  // Self-signed cert will be rejected
          }
          // Note: it doesn't seem to matter what you return for a proper SSL cert
          //       only self-signed certs
     }
     // If no other authentication is required, return NO for everything else
     // Otherwise maybe YES for NSURLAuthenticationMethodDefault and etc.
     return NO;
}



NSURLRequest ha un metodo privato chiamato setAllowsAnyHTTPSCertificate:forHost: che farà esattamente ciò che desideri. È possibile definire il metodo allowsAnyHTTPSCertificateForHost: su NSURLRequest tramite una categoria e impostarlo per restituire YES per l'host che si desidera sovrascrivere.




Links