UIWebView iOS中的客户端证书身份validation

我是新的目标c,但我正在开发一个应用程序,它有一个UIWebView加载一些网页内容。 所有的网页都需要客户端证书来进行身份validation,而我正在为露天而苦苦挣扎。 有谁知道如何在UIWebView中实现它的stream程?

谢谢!

为了避免UIWebView中的任何问题,您必须在Web视图的请求之前向客户端请求网站根目录和客户端证书。 你可以使用UIWebViewDelegate方法:

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

在此之后,UIWebView将能够加载一切没有任何问题。

如果您是Objective-C的新手,我想您也是基础框架的新手,所以这里有一些帮助。

为了解决这个问题,我使用ASIHTTPRequest,因为它已经embedded到我们的项目中了。 但是你可以使用NSURLConnection并且在NSURLConnectionDelegate方法中执行逻辑:

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

所以,这是我的代码在UIWebView请求之前向ASIHTTPRequest提供客户端证书:

 -(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; } 

我发送请求同步,以确保其完成,让UIWebView开始加载。

我使用一种方法从证书中检索身份,即:

 - (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; } 

这里使用相同的技术,但使用NSURLConnection而不是ASIHTTPRequest

  • 得到你的SecIdentityRef和你的SecCertificateRef
  • 用这些信息创build一个NSURLCredential
  • 将这个NSURLCredential发送给连接中的[challenge sender]:didReceiveAuthenticationChallenge:方法

要使用具有NSURLConnection的证书,您必须实现NSURLConnectionDelegate方法:

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

在这种方法中,NSURLConnection告诉你它已经收到了挑战。 你将不得不创build一个NSURLCredential来发送回[challenge sender]

所以你创build你的NSURLCredential:

 + (NSURLCredential *)credentialWithIdentity:(SecIdentityRef)identity certificates:(NSArray *)certArray persistence:(NSURLCredentialPersistence)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); NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(NSArray *)myCerts persistence:NSURLCredentialPersistencePermanent]; CFRelease(myCerts); } 

最后使用它

 - (void)useCredential:(NSURLCredential *)credential forAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 

在[挑战发件人]上

你应该有一切需要的。 祝你好运。