Как связаться с клиентским сертификатом, используя WebView в Какао? - PullRequest
0 голосов
/ 15 апреля 2011

Я пытаюсь подключиться к серверу, для которого требуется сертификат клиента. Таким образом, нормальный поток событий, который происходит при просмотре на этом сервере, заключается в том, что веб-браузер (как Safari, так и Chrome) предлагает пользователю выбрать сертификат и повторить операцию.

Так, как я могу сделать это во встроенном WebView в проекте Какао? До сих пор я определил, что ошибка возникает в методе didFailProvisionalLoadWithError:

- (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame {
    NSLog(@"webView:didFailProvisionalLoadWithError:forFrame:");
    NSLog(@"    error = %@", error);
}

Ошибка действительно error = Error Domain=NSURLErrorDomain Code=-1206 UserInfo=0x1006a8030 "The server “myserver.xxx” requires a client certificate.
Но как я могу отобразить диалоговое окно, чтобы пользователь мог выбрать сертификат из цепочки для ключей?

Ответы [ 2 ]

3 голосов
/ 14 июня 2011

Проблема решена.

Причиной была (известная) проблема с компонентом WebView.Открыл билет поддержки DTS с Apple и получил обходной путь.

РЕДАКТИРОВАТЬ: Вот обходной путь от DTS (я не знаю, действует ли он еще, так как это было 3 года назад):

Магнус ОК, у меня была возможность посмотреть на это, и я знаю, что происходит.Прежде чем мы начнем говорить о WebView, мне нужно познакомить вас с методами делегатов, используемыми NSURLConnection, который является базовым API, используемым для фактической загрузки данных из сети.NSURLConnection начал поддерживать одиночный обратный вызов делегата аутентификации -connection: didReceiveAuthenticationChallenge:, которому он прошел различные задачи аутентификации, которые поддерживались в то время (проблемы имени пользователя / пароля).В Mac OS X 10.6 (и iOS 3.0) NSURLConnection была улучшена для поддержки двух дополнительных типов проблем аутентификации для соединений TLS: o проблемы идентификации клиента (NSURLAuthenticationMethodClientCertificate), предоставляя делегату возможность выбрать идентификатор клиента для данного соединения TLS o серверавызовы доверия (NSURLAuthenticationMethodServerTrust), предоставляя делегату возможность переопределить оценку доверия сервера для данного соединения TLS. Из соображений совместимости невозможно было передать эти вызовы делегату при любых обстоятельствах, поэтому NSURLConnection представила новый обратный вызов делегата -connection: canAuthenticateAgainstProtectionSpace :, который позволяет делегату принять участие в решении этих задач.* * * Теперь давайте вернем это в ваше приложение.Как я уже упоминал, WebView использует NSURLConnection и для каждого соединения выступает в качестве делегата соединения.Он перехватывает вызовы аутентификации и передает их своему делегату загрузки ресурсов.Это прекрасно работает для задач аутентификации старой школы, потому что WebView справляется с задачей без необходимости делать что-то особенное;но это не удается для проблем аутентификации соединения TLS, потому что делегат должен выбрать в этих проблемах.Что вам действительно нужно, так это версия WebA для проверки подлинности canAuthenticateAgainstProtectionSpace.Что ж, получается, что это на самом деле реализовано.Просматривая открытый исходный код для WebView, я обнаружил, что существует обратный вызов частного делегата -webView: resource: canAuthenticateAgainstProtectionSpace: forDataSource:, который делает именно то, что вы хотите.http://www.opensource.apple.com/source/WebKit/WebKit-7533.20.25/mac/WebView/WebResourceLoadDelegatePrivate.h Если вы реализуете этот метод, вы можете подключиться к задаче аутентификации идентификации клиента и, основываясь на этой задаче, представить пользовательский интерфейс, который позволяет пользователю выбрать идентичность.Я прототипировал это в вашем тестовом приложении, и оно работает очаровательно.Вот код, который я использовал для получения запроса идентификации клиента: - (BOOL) webView: (WebView *) ресурс отправителя: (id) идентификатор canAuthenticateAgainstProtectionSpace: (NSURLProtectionSpace *) protectionSpace forDataSource: (WebDataSource *) dataSource {NSLog (@ "% @)", [protectionSpace authenticationMethod]);return [[protectionSpace authenticationMethod] isEqual: NSURLAuthenticationMethodClientCertificate];} и вот код, который я использовал для ответа на него: - (void) webView: (WebView *) ресурс отправителя: (id) идентификатор didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *) вызов из DataSource: (WebDataSource *) dataSource {NSLog (@ "didReceiveAuthenticationChallenge));NSString * authenticationMethod = [[challenge protectionSpace] authenticationMethod];NSLog (@ "authenticationMethod =% @", authenticationMethod);

 [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge]; }

Очевидно, что в реальном приложении вам нужно будет отобразить некоторый пользовательский интерфейс, а затем, как только пользователь выберет идентификатор клиента, создайте учетные данныедля него (+ [NSURLCredential credentialWithIdentity: сертификаты: постоянство:]), а затем применить эти учетные данные к участию(-UseCredential: forAuthenticationChallenge :). * * * Так, откуда ты продолжаешь? Независимо от того, что еще вы делаете, вы должны сообщить об ошибке в WebView, чтобы получить -webView: resource: canAuthenticateAgainstProtectionSpace: forDataSource: делегирование обратного вызова, опубликованного в общедоступных заголовках. Это очевидно, и самое досадное упущение. http://developer.apple.com/bugreporter/ После того, как вы подали ошибку, пожалуйста, пришлите мне номер ошибки, чтобы я мог связать это с этим инцидентом. Помимо этого, путь вперед меньше Чисто. Если вы создаете приложение не для Mac App Store, моя рекомендация было бы, что вы просто реализуете 'canAuthenticateAgainstProtectionSpace' делегат обратного вызова, как я показано выше и двигаться дальше со своей жизнью. ОТО, если вы создаете Mac App Store приложение, где использование частного API, в том числе делегата обратные вызовы, строго запрещено, жизнь становится намного сложнее. Разрешите в этом случае мы можем обсудить ваши варианты. Поделитесь и наслаждайтесь

1 голос
/ 19 апреля 2011

Установите WebResourceLoadDelegate и реализуйте методы делегирования, связанные с проверкой подлинности.Вам будет предложено при получении запроса на аутентификацию, когда вы сможете предоставить сертификат для использования.

ETA: Вот как вы можете создать NSURLCredential из сертификата, хранящегося в clientSide.p12:

NSString *thePath = [[NSBundle mainBundle]
        pathForResource:@"clientside" ofType:@"p12"];
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data = (CFDataRef)PKCS12Data;    
SecIdentityRef identity;
SecTrustRef trust;
extractIdentityAndTrust(inPKCS12Data, &identity, &trust);

SecCertificateRef certificate = NULL;
SecIdentityCopyCertificate (identity, &certificate); 

const void *certs[] = {certificate};
CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);

NSURLCredential *credential = [NSURLCredential
        credentialWithIdentity:identity
        certificates:(NSArray*)certArray
        persistence:NSURLCredentialPersistencePermanent];

Это происходит от другого вопроса .Вы также можете найти этот вопрос полезным.Я нашел их в Google для «nsurlcredential Certificate».

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