Allow unverified ssl certificates in WKWebView

ぃ、小莉子 提交于 2019-11-28 17:04:09
jvoll

This is fixed in iOS 9! WKWebView finally makes calls to webView(_:didReceiveAuthenticationChallenge:completionHandler:) on WKNavigationDelegate. Unfortunately this does not work if you run code built in Xcode 7 on iOS 8 devices (at least not in my initial testing).

In my example below, I'm not actually doing anything with the cert and just letting it pass through without doing any further validation (obviously a bad plan for production code). See Apple's docs (Listing 3) for more details of what they want you to do here.

Swift:

func webView(webView: WKWebView, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge,
    completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
        let cred = NSURLCredential.init(forTrust: challenge.protectionSpace.serverTrust!)
        completionHandler(.UseCredential, cred)
}

Swift 3:

let cred = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, cred)

Swift 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);

Looks like there may not be a solution at this stage (iOS 8.1.1). One might have expected the WKNavigationDelegate method webView:didReceiveAuthenticationChallenge:completionHandler: to handle this, but based on this Apple developer forum discussion an Apple employee confirms that this delegate method currently doesn't get called when self-signed certificates are encountered.

Try this:

 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)
    }

}

I have the same error, and try to solve it using the Most Voted answer above, I used the following code to create a NSURLCredential object, but it failed.

NSURLCredential * credential = [[NSURLCredential alloc] initWithTrust:[challenge protectionSpace].serverTrust];

Then I found a solution in Apple Developer Forums. This helped me :

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

Open the URL in Safari on the device once, there you will be prompted with the option to accept the certificate. Once accepted it should work in your app as well, as the certificate is now known to the device. This is a per device workaround, it will in no way affect your app at release time.

I spent a lot of time looking into this, as an ios newbie, none of the solutions proposed were complete in my opinion. So here is what I did to get WKWebView to work in my case (very simple web view that needs access to self signed cert for dev only):

First thing: in my root Info.plist file, I added "App Transport Security Settings" as a dictionary, and add "Allow Arbitrary Loads" item with a value of YES.

Second: I added this code to my ViewController (inherits UIViewController and WKNavigationDelegate) - this was sourced from several answers elsewhere

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))
}

NOTE THAT THIS SOLUTION WILL LIKELY BE REJECTED BY THE APP STORE - I WILL SUBMIT TO THE APP STORE WITH "Allow Arbitrary Loads" ITEM WITH A VALUE OF NO.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!