Разрешить непроверенные сертификаты ssl в WKWebView
Я пытаюсь загрузить URL-адрес HTTPS с самозаверяющим сертификатом в WKWebView для iOS 8, и он продолжает терпеть неудачу. Обходной путь, используемый с UIWebView (с использованием setAllowsAnyHTTPSCertificate из NSUrlRequest), похоже, не работает. Кто-нибудь знает об обходном пути?
Мне не нужно решение, справедливое для AppStore, так как мне нужно только получить доступ к самозаверяющим сайтам сертификатов на этапах разработки, а не на производстве, но это действительно проблема для разработки и тестирования экземпляров сервера.
Спасибо заранее.
Ответы
Ответ 1
Это исправлено в iOS 9! WKWebView
выполняет вызовы webView(_:didReceiveAuthenticationChallenge:completionHandler:)
в WKNavigationDelegate
. К сожалению, это не работает, если вы запускаете код, встроенный в Xcode 7, на устройствах iOS 8 (по крайней мере, в моем первоначальном тестировании).
В моем примере ниже я на самом деле ничего не делаю с сертификатом, а просто пропускаю его без дальнейшей проверки (очевидно, плохой план для производственного кода). См. Apple Docs (листинг 3) для более подробной информации о том, что они хотят, чтобы вы делали здесь.
Swift:
func webView(webView: WKWebView, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge,
completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
let cred = NSURLCredential.init(forTrust: challenge.protectionSpace.serverTrust!)
completionHandler(.UseCredential, cred)
}
Свифт 3:
let cred = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, cred)
Свифт 4:
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
let cred = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, cred)
}
Objective-C
NSURLCredential * credential = [[NSURLCredential alloc] initWithTrust:[challenge protectionSpace].serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
Ответ 2
Похоже, на данном этапе не может быть решения (iOS 8.1.1). Можно было бы ожидать, что метод WKNavigationDelegate webView:didReceiveAuthenticationChallenge:completionHandler:
справится с этим, но на основе этого обсуждения форума разработчиков Apple сотрудник Apple подтверждает, что этот метод делегата в настоящее время не вызывается, когда встречаются самоподписанные сертификаты.
Ответ 3
У меня такая же ошибка, и я попытаюсь решить ее, используя вышеприведенный ответ, я использовал следующий код для создания объекта NSURLCredential
, но он не удался.
NSURLCredential * credential = [[NSURLCredential alloc] initWithTrust:[challenge protectionSpace].serverTrust];
Затем я нашел решение в Форумы разработчиков Apple. Это помогло мне:
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
NSLog(@"Allow all");
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
CFDataRef exceptions = SecTrustCopyExceptions (serverTrust);
SecTrustSetExceptions (serverTrust, exceptions);
CFRelease (exceptions);
completionHandler (NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:serverTrust]);
}
Ответ 4
Откройте URL-адрес в Safari на устройстве один раз, там вам будет предложено выбрать сертификат. После принятия он должен работать и в вашем приложении, так как сертификат теперь известен устройству.
Это обходное решение для каждого устройства, оно никоим образом не повлияет на ваше приложение во время выпуска.
Ответ 5
Я потратил много времени, изучая это, как новичок ios, ни одно из предложенных решений, на мой взгляд, не было полным. Итак, вот что я сделал, чтобы заставить WKWebView работать в моем случае (очень простое веб-представление, которому нужен доступ к самозаверяющему сертификату только для dev):
Первое: в своем корневом файле Info.plist я добавил "Настройки безопасности транспорта транспорта" в качестве словаря и добавил пункт "Разрешить произвольные загрузки" со значением YES.
![App Transport Security Settings Allow Arbitrary Loads]()
Второе: я добавил этот код в свой ViewController (наследует UIViewController и WKNavigationDelegate) - это было получено из нескольких ответов в других местах.
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard let serverTrust = challenge.protectionSpace.serverTrust else { return completionHandler(.useCredential, nil) }
let exceptions = SecTrustCopyExceptions(serverTrust)
SecTrustSetExceptions(serverTrust, exceptions)
completionHandler(.useCredential, URLCredential(trust: serverTrust))
}
ОТМЕТЬТЕ, ЧТО НАСТОЯЩЕЕ РЕШЕНИЕ ПОТРЕБНО БУДЕТ ОТКАЗАНО МАГАЗИНОМ ПРИЛОЖЕНИЯ - Я ПРЕДСТАВлю МАГАЗИН ПРИЛОЖЕНИЯ С ПУНКТОМ "Разрешить произвольные загрузки" со значением НЕТ.
Ответ 6
Попробуй это:
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if let serverTrust = challenge.protectionSpace.serverTrust {
let credential = URLCredential(trust: serverTrust)
completionHandler(.useCredential, credential)
}else{
completionHandler(.useCredential, nil)
}
}
Ответ 7
Следующее работает в моем случае для загрузки либо HTTP или HTTPS URL
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
return completionHandler(.useCredential, nil)
}
В случае, если вы загружаете небезопасный HTTP-URL, такой как http://www.example.com
, вам нужно открыть Info.plist
и включить NSExceptionAllowsInsecureHTTPLoads
, например:
![enter image description here]()
Ответ 8
URL-объект:
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:requestObj delegate:self];
[connection start];
И затем добавьте это в свой делегат:
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
else
{
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[resultData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *htmlString = [[NSString alloc] initWithBytes:[resultData bytes] length:[resultData length] encoding:NSUTF8StringEncoding];
[webView loadHTMLString:htmlString baseURL:url];
}