Obiettivo-C/Cacao:Come posso accettare un certificato server non valido?
-
08-06-2019 - |
Domanda
Utilizzando NSURLRequest, sto tentando di accedere a un sito Web con un certificato scaduto.Quando invio la richiesta, my connessione: didFailWithError il metodo delegato viene richiamato con le seguenti informazioni:
-1203, NSURLErrorDomain, bad server certificate
Le mie ricerche hanno prodotto solo una soluzione:un metodo di classe nascosta in NSURLRequest:
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:myHost];
Tuttavia, non voglio utilizzare API private in un'app di produzione per ovvi motivi.
Qualche suggerimento su cosa fare?Devo utilizzare le API CFNetwork e, in tal caso, due domande:
- Qualche codice di esempio che posso utilizzare per iniziare?Non ne ho trovato nessuno online.
- Se utilizzo CFNetwork per questo, devo abbandonare completamente NSURL?
MODIFICARE:
iPhone OS 3.0 ha introdotto un metodo supportato per eseguire questa operazione.Maggiori dettagli qui: Come utilizzare NSURLConnection per connettersi con SSL per un certificato non attendibile?
Soluzione 3
iPhone OS 3.0 ha introdotto un modo supportato per eseguire questa operazione che non richiede le API CFNetwork di livello inferiore.Maggiori dettagli qui:
Come utilizzare NSURLConnection per connettersi con SSL per un certificato non attendibile?
Altri suggerimenti
Il modo supportato per eseguire questa operazione richiede l'utilizzo di CFNetwork.Quello che devi fare è allegare un kCFStreamPropertySSLSettings allo stream che specifica kCFStreamSSLValidatesCertificateChain == kCFBooleanFalse.Di seguito è riportato un codice rapido che lo fa, senza verificare la validità dei risultati e aggiungere la pulizia.Una volta fatto questo puoi usare CFReadStreamRead() per ottenere i dati.
CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, CFSTR("http://www.apple.com"), NULL);
CFHTTPMessageRef myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), myURL, kCFHTTPVersion1_1);
CFReadStreamRef myStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, myRequest);
CFMutableDictionaryRef myDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(myDict, kCFStreamSSLValidatesCertificateChain, kCFBooleanFalse);
CFReadStreamSetProperty(myStream, kCFStreamPropertySSLSettings, myDict);
CFReadStreamOpen(myStream);
Se si tratta di un server interno a scopo di test, perché non importare semplicemente il certificato del server di test nel KeyChain e impostare impostazioni di attendibilità personalizzate?
Ho riscontrato lo stesso problema: stavo sviluppando un client SOAP e il server di sviluppo ha un certificato "fatto in casa".Non sono riuscito a risolvere il problema nemmeno utilizzando quel metodo, dal momento che non stavo utilizzando NSURL, ma i metodi WS (scarsamente documentati e apparentemente abbandonati) e per il momento ho deciso di utilizzare (internamente) solo un metodo non SSL connessione.
Detto questo, tuttavia, la domanda che mi viene in mente è: se non sei disposto a utilizzare un'API privata in un'app di produzione, dovresti consentire l'accesso a un sito con un certificato poco affidabile?
Citerò Jens Alfke:
Questo non è solo un problema di sicurezza teorico.Qualcosa
Secondo i dati, circa il 25% dei server DNS pubblici sono stati compromessi
rapporti recenti e possono indirizzare gli utenti anche a siti di phishing/malware/pubblicitari
se inseriscono correttamente il nome di dominio.L'unica cosa che ti protegge
da questo c'è il controllo del certificato SSL.
Puoi creare un certificato autofirmato e aggiungere la tua autorità di certificazione personalizzata alle CA attendibili?Non sono del tutto sicuro di come funzionerebbe su iPhone, ma suppongo che su Mac OS X li aggiungeresti al portachiavi.
Potrebbe interessarti anche questo post Rif:Come gestire l'errore del certificato errato in NSURLDownload
Un'altra opzione potrebbe essere quella di utilizzare una libreria di connessioni alternativa.
Sono un grande fan di AsyncSocket e supporta i certificati autofirmati
http://code.google.com/p/cocoaasyncsocket/
Dai un'occhiata, penso che sia molto più robusto dello standard NSURLRequests.