有没有人找到使用UIWebView加载带有无效服务器证书的HTTPS页面的方法?

时间:2013-01-10 22:13:12

标签: ios uiwebview

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

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

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

这是不一致的 - 当然,UIWebView的行为应该与Safari的行为类似,以便在iPhone本身内保持一致吗? 它也是一个愚蠢的NSURLConnection允许NSURLRequest具有完全的灵活性:setAllowsAnyHTTPSCertificate是私有的。

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

干杯

P.S。 请不要讨论有关为什么有人想要这样做的讨论,非常感谢。

2 个答案:

答案 0 :(得分:14)

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

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

这一切似乎都很好。

答案 1 :(得分:1)

从马的嘴里说:

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

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