在 WKWebView 中允许未经验证的 ssl 证书

问题描述 投票:0回答:8

我正在尝试在 iOS 8 的 WKWebView 中加载带有自签名证书的 HTTPS url,但它一直失败。与 UIWebView 一起使用的解决方法(使用来自 NSUrlRequest 的 setAllowsAnyHTTPSCertificate)似乎不起作用。有谁知道任何解决方法?

我不需要对 AppStore 有效的解决方案,因为我只需要在开发阶段访问自签名证书站点,而不是在生产阶段,但这确实是开发和测试服务器实例的问题。

提前谢谢你。

ios ssl uiwebview self-signed wkwebview
8个回答
67
投票

这已在 iOS 9 中修复!

WKWebView
终于在
webView(_:didReceiveAuthenticationChallenge:completionHandler:)
打电话给
WKNavigationDelegate
。不幸的是,如果您在 iOS 8 设备上运行 Xcode 7 中构建的代码,这将不起作用(至少在我的初始测试中不会)。

在我下面的例子中,我实际上并没有对证书做任何事情,只是让它通过而不做任何进一步的验证(对于生产代码来说显然是一个糟糕的计划)。请参阅 Apple 的文档(清单 3),了解他们希望您在此处执行的操作的更多详细信息。

斯威夫特:

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

目标-C

NSURLCredential * credential = [[NSURLCredential alloc] initWithTrust:[challenge protectionSpace].serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);

14
投票

我花了很多时间研究这个,作为一个 ios 新手,我认为提出的解决方案都不是完整的。所以这就是我为让 WKWebView 在我的案例中工作所做的事情(非常简单的 Web 视图需要访问 dev only 的自签名证书):

第一件事:在我的根 Info.plist 文件中,我将“App Transport Security Settings”添加为字典,并添加值为 YES 的“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))
}

请注意,此解决方案可能会被应用商店拒绝 - 我将提交给应用商店,其中包含“允许任意加载”项目,其值为 NO.


8
投票

我有同样的错误,并尝试使用上面投票最多的答案来解决它,我使用以下代码创建了一个

NSURLCredential
对象,但它失败了

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

然后我在Apple Developer Forums中找到了解决方案。这对我有帮助:

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

7
投票

试试这个:

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

}

4
投票

看起来在这个阶段可能没有解决方案(iOS 8.1.1)。人们可能期望 WKNavigationDelegate 方法

webView:didReceiveAuthenticationChallenge:completionHandler:
来处理这个问题,但基于这个 Apple 开发者论坛讨论,一位 Apple 员工确认当前在遇到自签名证书时不会调用此委托方法。


1
投票

在设备上的 Safari 中打开 URL 一次,系统将提示您选择接受证书。一旦被接受,它也应该在您的应用程序中工作,因为设备现在知道该证书。 这是针对每个设备的解决方法,它不会在发布时影响您的应用程序。


0
投票

iOS 10+ 忽略

NSAllowsArbitraryLoads
:检查here。并对其他标志保持谨慎,因为 Apple 将要求 AppStore 审查的理由。并且忽略UIWebview相关的解决方案,Apple无论如何都会拒绝它。

简单的方法

  1. 在设备上下载自签名根 CA
  2. 在设置>关于> ...证书中信任它..

这显然不适合大量的目标受众。

更好但更难的方法

  1. 阅读指南
  2. 实施 WKNavigationDelegate
    webView(_:didReceive:completionHandler:)

更多关于 websocket (OSError -9807)

websocket 有一个未修复的 webkit 错误(自 2015 年以来!),它是不同的身份验证路由,因此目前无法覆盖系统默认行为。 Apple 论坛主题:


0
投票

解决方法-在设备上的“文件”中下载/保存证书,安装它,信任证书,然后转到证书信任设置并启用对根证书的完全信任。你现在应该好了。这仅用于开发测试,与生产版本无关。希望能帮助并为其他人节省一些时间。

© www.soinside.com 2019 - 2024. All rights reserved.