Подтвердить что ты не робот

Разрешить непроверенные сертификаты ssl в WKWebView

Я пытаюсь загрузить URL-адрес HTTPS с самозаверяющим сертификатом в WKWebView для iOS 8, и он продолжает терпеть неудачу. Обходной путь, используемый с UIWebView (с использованием setAllowsAnyHTTPSCertificate из NSUrlRequest), похоже, не работает. Кто-нибудь знает об обходном пути?

Мне не нужно решение, справедливое для AppStore, так как мне нужно только получить доступ к самозаверяющим сайтам сертификатов на этапах разработки, а не на производстве, но это действительно проблема для разработки и тестирования экземпляров сервера.

Спасибо заранее.

4b9b3361

Ответ 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];
}