Autenticación de certificate de cliente en UIWebView iOS

Soy un poco nuevo en el objective c, pero estoy desarrollando una aplicación que tiene un UIWebView que carga un poco de contenido web. Todas las páginas web requieren un certificate de cliente para la authentication y estoy luchando con él por días de rocío. ¿Alguien sabe el flujo de cómo implementarlo en UIWebView?

¡Gracias!

Para evitar cualquier problema en UIWebView, debe hacer una request a su website raíz, con el certificate del cliente, antes de la request de la vista web. Puede usar el método UIWebViewDelegate:

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 

Después de esto, el UIWebView podrá cargar todo sin ningún problema.

Si eres nuevo en Objective-C, supongo que también eres nuevo en el marco de la Fundación, así que aquí hay un poco de ayuda.

Para resolver esto, utilicé ASIHTTPRequest ya que estaba embedded en nuestro proyecto. Pero puede usar una NSURLConnection y hacer la lógica en el método NSURLConnectionDelegate:

 - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 

Entonces, aquí está mi código para proporcionar un certificate de cliente a un ASIHTTPRequest antes de una request de UIWebView:

 -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { SecIdentityRef identity = NULL; SecTrustRef trust = NULL; NSData *PKCS12Data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"test.cert" ofType:@"pfx"]]; [self extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data]; NSURL *serverUrl = [NSURL URLWithString:URL_SECURE_SERVER]; ASIHTTPRequest *firstRequest = [ASIHTTPRequest requestWithURL:serverUrl]; [firstRequest setValidatesSecureCertificate:NO]; [firstRequest setClientCertificateIdentity:identity]; [firstRequest startSynchronous]; return YES; } 

Estoy enviando la request sincrónicamente para garantizar que se complete antes de permitir que UIWebView comience a cargarse.

Utilizo un método para recuperar la identidad del certificate, que es:

 - (BOOL)extractIdentity:(SecIdentityRef *)outIdentity andTrust:(SecTrustRef*)outTrust fromPKCS12Data:(NSData *)inPKCS12Data { OSStatus securityError = errSecSuccess; NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:@"mobigate" forKey:(id)kSecImportExportPassphrase]; CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); securityError = SecPKCS12Import((CFDataRef)inPKCS12Data,(CFDictionaryRef)optionsDictionary,&items); if (securityError == 0) { CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0); const void *tempIdentity = NULL; tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity); *outIdentity = (SecIdentityRef)tempIdentity; const void *tempTrust = NULL; tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust); *outTrust = (SecTrustRef)tempTrust; } else { NSLog(@"Failed with error code %d",(int)securityError); return NO; } return YES; } 

Aquí la misma técnica, pero utilizando la connection NSURLC en lugar de la ASIHTTPRequest

  • obtenga su SecIdentityRef y su SecCertificateRef
  • Cree un NSURLCnetworkingential con esas infos.
  • envíe esta NSURLCnetworkingential al [remitente del desafío] en la connection: didReceiveAuthenticationChallenge: method

para usar un certificate con una NSURLConnection, debe implementar el método NSURLConnectionDelegate:

 - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 

En este método, la NSURLConnection le dice que recibió un desafío. Tendrá que crear un NSURLCnetworkingential para enviar de vuelta al [remitente del desafío]

Entonces creas tu NSURLCnetworkingential:

 + (NSURLCnetworkingential *)cnetworkingentialWithIdentity:(SecIdentityRef)identity certificates:(NSArray *)certArray persistence:(NSURLCnetworkingentialPersistence)persistence { NSString *certPath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"cer"]; NSData *certData = [[NSData alloc] initWithContentsOfFile:certPath]; SecIdentityRef myIdentity; // ??? SecCertificateRef myCert = SecCertificateCreateWithData(NULL, (CFDataRef)certData); [certData release]; SecCertificateRef certArray[1] = { myCert }; CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL); CFRelease(myCert); NSURLCnetworkingential *cnetworkingential = [NSURLCnetworkingential cnetworkingentialWithIdentity:myIdentity certificates:(NSArray *)myCerts persistence:NSURLCnetworkingentialPersistencePermanent]; CFRelease(myCerts); } 

Y finalmente utilízalo con

 - (void)useCnetworkingential:(NSURLCnetworkingential *)cnetworkingential forAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 

en [desafiante remitente]

Deberías tener todo lo que necesitas. Buena suerte.