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
在[挑战发件人]上
你应该有一切需要的。 祝你好运。