Проверка подлинности клиентского сертификата в UIWebView iOS - PullRequest
4 голосов
/ 28 февраля 2012

Я немного новичок в задаче c, но я разрабатываю приложение, которое имеет UIWebView, который загружает некоторый веб-контент.Все веб-страницы требуют сертификата клиента для аутентификации, и я борюсь с ним в течение дней росы.Кто-нибудь знает поток, как реализовать его в UIWebView?

Спасибо!

1 Ответ

8 голосов
/ 28 февраля 2012

Чтобы избежать каких-либо проблем в UIWebView, вы должны сделать запрос к корневому сайту с сертификатом клиента перед запросом веб-просмотра.Вы можете использовать метод UIWebViewDelegate:

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

После этого UIWebView сможет загрузить все без проблем.

Если вы новичок в Objective-C, я думаю, вытакже новый для платформы Foundation, так что здесь немного помощи.

Чтобы решить эту проблему, я использовал ASIHTTPRequest, поскольку он уже был встроен в наш проект.Но вы можете использовать NSURLConnection и выполнить логику в методе NSURLConnectionDelegate:

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

Итак, вот мой код для предоставления сертификата клиента для запроса 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.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
  • создайте NSURLCredential с этой информацией
  • отправьте обратно этоNSURLCredential [отправителю вызова] в соединении: didReceiveAuthenticationChallenge: метод

, чтобы использовать сертификат с NSURLConnection, необходимо реализовать метод NSURLConnectionDelegate:

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

Inэтот метод, NSURLConnection говорит вам, что он получил AChallenge.Вам нужно будет создать NSURLCredential для отправки обратно [отправителю вызова]

. Таким образом, вы создадите свой 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

на [вызов отправителя]

У вас должно быть все необходимое.Удачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...