11

如果用户尝试在 Mobile Safari 中加载 https 网页并且服务器的证书验证检查失败(其过期、撤销、自签名等),则会向用户显示一条警告消息并询问他们是否要继续或不。

类似地,NSURLConnection 让实现者能够首先决定如何检查证书,然后决定如果证书失败如何继续,因此在这种情况下也可以向用户显示警告并为他们提供继续加载的机会页面与否。

然而,当在 UIWebView 中加载一个未通过证书检查的 https 页面时,这种行为似乎只是无法加载该页面 - didFailLoadWithError: 使用 kCFURLErrorServerCertificateUntrusted 调用,但没有向用户显示任何内容。

这是不一致的 - UIWebView 行为肯定应该以与 Safari 类似的方式在 iPhone 内部保持一致吗?NSURLConnection 允许完全的灵活性也是一个愚蠢的做法,但 NSURLRequest:setAllowsAnyHTTPSCertificate 是私有的。

无论如何要实现与 Safari 一致的行为,是否可以以类似于 NSURLConnection 允许的方式自定义此默认行为?

干杯

PS 请不要进入关于为什么有人要这样做的光顾的旁白讨论,非常感谢。

4

2 回答 2

15

我发现了如何做到这一点:

1)当页面加载时会失败,因此在 didFailLoadWithError 中添加如下内容:

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
    if ([error.domain isEqualToString: NSURLErrorDomain])
    {
        if (error.code == kCFURLErrorServerCertificateHasBadDate        ||
            error.code == kCFURLErrorServerCertificateUntrusted         ||
            error.code == kCFURLErrorServerCertificateHasUnknownRoot    ||
            error.code == kCFURLErrorServerCertificateNotYetValid)
        {
        display dialog to user telling them what happened and if they want to proceed

2)如果用户想要加载页面,那么您需要使用 NSURLConnection 进行连接:

NSURLRequest *requestObj = [NSURLRequest requestWithURL:self.currentURL     cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:10.0];
self.loadingUnvalidatedHTTPSPage = YES;
[self.webView loadRequest:requestObj];

3) 然后对 shouldStartLoadWithRequest 进行此更改

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 
{
    if (self.loadingUnvalidatedHTTPSPage)
    {
        self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
        [self.connection start];
        return NO;
    }

4) 将 NSURLConnectionDelegate 实现为:

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    SecTrustRef trust = challenge.protectionSpace.serverTrust;
    NSURLCredential *cred;
    cred = [NSURLCredential credentialForTrust:trust];
    [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
}


- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
{
    NSURLRequest *requestObj = [NSURLRequest requestWithURL:self.currentURL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:10.0];
    self.loadingUnvalidatedHTTPSPage = NO;
    [self.webView loadRequest: requestObj];
    [self.connection cancel];
}

一切似乎都很好。

于 2013-01-11T21:18:04.540 回答
1

从马口中:

“UIWebView 没有为应用程序自定义其 HTTPS 服务器信任评估提供任何方式。使用公共 API 可以解决此限制,但这并不容易。如果您需要这样做,请联系开发人员技术支持(dts @apple.com)

来源:http: //developer.apple.com/library/ios/#technotes/tn2232/_index.html

于 2013-01-10T22:59:18.680 回答