UIWebView iOS中的客户端证书认证 [英] Client certificate authentication in UIWebView iOS

查看:281
本文介绍了UIWebView iOS中的客户端证书认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一个新的目标c,但我正在开发一个应用程序,它有一个UIWebView加载一些网络内容。所有的网页都需要客户端证书进行身份验证,而且我在为露天工作而努力。
任何人都知道如何在UIWebView中实现它。



谢谢!

解决方案

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

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

此后,UIWebView将能够加载任何问题。 / p>

如果你刚接触Objective-C,我想你也是Foundation框架的新手,所以这里有一些帮助。



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

   - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)挑战

所以,这里是我的代码提供客户端证书到ASIHTTPRequest到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.certofType:@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:@mobigateforKey:(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(@失败,错误代码%d,(int)securityError);
return NO;
}

return YES;
}

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




  • 获取您的SecIdentityRef和您的SecCertificateRef

  • 使用这些信息创建NSURLCredential

  • 将此NSURLCredential发送回连接中的[挑战发件人]:didReceiveAuthenticationChallenge:method



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

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

在这种方法中,NSURLConnection告诉你它收到了一个挑战。您必须创建一个NSURLCredential才能发送回[挑战发件人]



因此,您需要创建NSURLCredential:

  +(NSURLCredential *)credentialWithIdentity:(SecIdentityRef)身份证书:(NSArray *)certArray持久性(NSURLCredentialPersistence)持久性
{

NSString * certPath = [[NSBundle mainBundle] pathForResource:@certificateofType:@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 

[挑战发件人]



您应该拥有一切所需。祝你好运。


I'm kind of new in objective c, but I'm developing an app which has a UIWebView that loads some web content. All the web pages require client certificate for authentication and I'm struggling with it for dew days. Does anyone know the flow how to implement it in UIWebView?

Thanks!

解决方案

To avoid any problem in the UIWebView, you have to make a reques to you website root, with the client certificate, before the request of the web view. You can use the UIWebViewDelegate method:

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

After this, the UIWebView will be able to load everything without any problem.

If you are new to Objective-C, I guess you are also new to the Foundation framework so here's a bit of help.

To solve this, I used ASIHTTPRequest as it was already embedded in our project. But you can use a NSURLConnection and do the logic in the NSURLConnectionDelegate method:

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

So, here's my code to provide a client certificate to an ASIHTTPRequest prior to a UIWebView request:

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

I'm sending the request synchronously to ensure its completion before letting the UIWebView starts its loading.

I use a method to retrieve the identity from the certificate, which is:

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

Here the same technique, but using the NSURLConnection instead of the ASIHTTPRequest

  • get your SecIdentityRef and your SecCertificateRef
  • create a NSURLCredential with those infos
  • send back this NSURLCredential to the [challenge sender] in the connection:didReceiveAuthenticationChallenge: method

to use a certificate with a NSURLConnection, you have to implement the the NSURLConnectionDelegate method:

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

In this method, the NSURLConnection is telling you that it received a challenge. You will have to create a NSURLCredential to send back to the [challenge sender]

So you create your 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);
}

And finally use it with

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

on [challenge sender]

You should have everything needed. Good luck.

这篇关于UIWebView iOS中的客户端证书认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆