2011-07-22 30 views
26

Tenemos una aplicación de iOS que usa una UIWebView para mostrar contenido. Nos cargamos con los datos con código que se parece a esto:Ignorar certificados de servidor inválidos con UIWebView

NSURL *url = [NSURL URLWithString:myURLString]; 
NSURLRequest *request = [NSURLRequest requestWithURL:url]; 
[_webView setDelegate:self]; 
[_webView loadRequest:request]; 

Esto funcionaba bien con peticiones HTTP, pero ahora estamos usando HTTPS contra un servidor con un certificado SSL autofirmado. Cuando se ejecuta el anterior, el método se llama a webView:didFailLoadWithError: delegado, con este error:

The certificate for this server is invalid. You might be connecting to a server that is pretending to be "blah.blah.blah.com" which could put your confidential information at risk."

me gustaría simplemente ignorar el certificado no válido y seguir con la solicitud, ya que uno puede hacer en Mobile Safari.

He visto cómo evitar este problema al utilizar NSURLConnection (ver HTTPS request on old iphone 3g, por ejemplo), pero ¿qué se puede hacer con un UIWebView?

Imagino que podría volver a trabajar el código para que use NSURLConnection para hacer las solicitudes y luego ponga los resultados en la vista web llamando a su método loadHTMLString:baseURL:, pero eso se complicará cuando las páginas tengan imágenes, CSS, JavaScript, y así sucesivamente. hay una manera mas facil?

Respuesta

0

Por lo que yo sé, eso no es posible con solo UIWebView. Según lo entiendo, debe usar NSURLConnection para manejar todo el mojo HTTP/HTTPS y luego alimentar sus resultados al UIWebView a través de -loadHtmlString:baseURL: o -loadData:MIMEType:textEncodingName:baseURL:.

21

Tenga en cuenta: Esta API no está soportada actualmente, y solo debería utilizarse en un entorno de prueba seguro. Para obtener más detalles, eche un vistazo a este CocoaNetics article.

[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]]; le permitirá ignorar los errores del certificado. También tendrá que añadir lo siguiente al principio del archivo que le conceda acceso a estas APIs privadas:

@interface NSURLRequest (DummyInterface) 
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host; 
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host; 
@end 
+4

El uso de este enfoque hará que su aplicación sea rechazada por AppStore. – Franklin

+9

Es perfecto para usar un certificado de servidor local autofirmado. Lo rodeé todo con '#if DEBUG' para no ser rechazado. – bendytree

16

Sólo para que todo el mundo sabe ... el uso anterior de interfaces ocultos no serán aceptadas por Apple. Buscan el uso de API privadas y NO es una solución aceptable. Por lo tanto, no publique la solución descrita anteriormente como LA forma de solucionarlo porque, aunque funciona, le comprará un rechazo en la AppStore. Eso lo hace inútil.

Lo que sigue es el método ACEPTABLE de ignorar certificados de servidor no válidos. Es necesario utilizar NSURLConnection y cargar los datos de la página web de forma manual, así:

. 
. 
. 
    //Create a URL object. 
    url = [NSURL URLWithString:urlAddress]; 
    NSURLRequest *requestObj = [NSURLRequest requestWithURL:url]; 
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:requestObj delegate:self]; 
    [connection start]; 
} 

Y luego, en su delegado ....

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace 
{ 
    return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
{ 
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) 
    { 
     [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; 
    } 
    else 
    { 
     [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; 
    } 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
[resultData appendData:data]; 
} 


- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    NSString *htmlString = [[NSString alloc] initWithBytes:[resultData bytes] length:[resultData length] encoding:NSUTF8StringEncoding]; 
    [webView loadHTMLString:htmlString baseURL:url]; 
} 
@end 

Dónde resultData es un NSMutableData que instanciado anteriormente y donde url y urlAddress son cosas que has instanciado y completado en otro lugar.

Desafortunadamente, actualmente no sé cómo obtener UIWebView real para cargar una página directamente sin tener un certificado válido.

Suyo, GC

+2

problema con este enfoque es que su vista web no mostrará ningún contenido dinámico: CSS no se cargará, javascript o cualquier llamada REST incrustada etc. Este es mi problema por el momento. Hay una forma enrevesada de hacerlo sugerido [aquí] (http://stackoverflow.com/questions/11573164/uiwebview-to-view-self-signed-websites-no-private-api-not-nsurlconnection-i) – Stretch

+0

This no es una solución aceptable para páginas web dinámicas que, por ejemplo. tiene javascript que depende de window.location después de los redireccionamientos. El propio UIWebView necesita administrar su ubicación y manejar los redireccionamientos, algo que no se puede hacer al alimentar los datos desde un NSURLConnection. – davidgoli

3

Resulta que una vez que el sitio es autenticado por un NSURLConnection cancelado, la UIWebView puede hacer peticiones al sitio.There is a complete explanation here.

+0

Esta respuesta: http://stackoverflow.com/questions/11573164/uiwebview-to-view-self-signed-websites-no-private-api-not-nsurlconnection-i/15074358#15074358 tiene una forma inteligente de resolver este problema . – zadr

Cuestiones relacionadas