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

Gru*_*kes 10 uiwebview ios

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

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

但是,似乎在UIWebView中加载https页面时,证书检查失败,行为只是无法加载页面 - didFailLoadWithError:使用kCFURLErrorServerCertificateUntrusted调用,但是没有任何内容显示给用户.

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

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

干杯

PS请不要进入有关为什么有人想要这样做的旁观讨论,非常感谢你.

Gru*_*kes 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
Run Code Online (Sandbox Code Playgroud)

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

NSURLRequest *requestObj = [NSURLRequest requestWithURL:self.currentURL     cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:10.0];
self.loadingUnvalidatedHTTPSPage = YES;
[self.webView loadRequest:requestObj];
Run Code Online (Sandbox Code Playgroud)

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;
    }
Run Code Online (Sandbox Code Playgroud)

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];
}
Run Code Online (Sandbox Code Playgroud)

这一切似乎都很好.