天天看点

iOS访问 self-signed(自签名) HTTPSiOS 访问 自签名 HTTPS

iOS 访问 自签名 HTTPS

Background:

最近项目组长要求做一个客户提出的的需求, 支持客户内网服务器. 而他的服务器为了省事直接升级 HTTPS 后用了假证书. 于是, 开始了iOS7,8,9系统下的各种坑..

Content:

对于没有 CA 认证过的 HTTPS 是不能够被直接信任的, 称为自签名 HTTPS, 访问此类服务器时会有类似下面的提示:

 MAC OSX Safari:
iOS访问 self-signed(自签名) HTTPSiOS 访问 自签名 HTTPS

iPhone iOS Safari:

iOS访问 self-signed(自签名) HTTPSiOS 访问 自签名 HTTPS

但是开发过程中, 我们使用的 UIWebView 和 WKWebView 并不会跳出此弹框来让我们选择.所以, 我们需要在代码内进行手动添加信任.

首先我们需要在 info.plist 内添加此节点:

iOS访问 self-signed(自签名) HTTPSiOS 访问 自签名 HTTPS

iOS 7 :

目前市面的 APP 还是有很多需要兼容 iOS7 的系统的, 而 WKWebView 最低支持 iOS8.0系统, 所以在7上访问 自签名 HTTPS 时, 必须使用 UIWebView ,可以按以下步骤: 1, 首先拿到需要特殊处理的链接.(i:可以通过服务器下发, 只有公司信任的此类 HTTPS 可以被访问. ii: 全部HTTPS允许, 存在安全隐患, 但操作简单.) 2, 使用此链接创建一个 NSURLConnection 对象, 并设置代理, 实现 NSURLConnectionDelegate 的三个方法:

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:URLString]] delegate:self];

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace

{

    return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];

}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge

{

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])

    {

        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]forAuthenticationChallenge:challenge];

    }

    //if ([self.trustedHosts containsObject:self.trustedURL]) {

    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];

    //}

}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

{

    [self.webView loadRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:self.trustedURL]]];

    [connection cancel];

}

iOS8:

iOS8开始, 可以使用苹果推出的全新的 web 类库, 它由原来的 UIWebView 重新封装优化后形成的类和3个协议组成. 由于苹果的 BUG, WKWebView 在 iOS8 上访问 self-signed HTTPS 并不会回调 -didReceiveChallenge, 所以想在 iOS8上访问 自签名 HTTPS 还是得使用 UIWebView. 步骤同上.

iOS9:

iOS9, 苹果默默修复了 WKWebView 的-didReceiveChallenge方法. 使用WKWebView 和 UIWebView 类似:

    [self.wkWebView loadRequest:request];

    self.wkWebView.navigationDelegate = self;

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

    decisionHandler(WKNavigationActionPolicyAllow);

}

- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])

    {

        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]forAuthenticationChallenge:challenge];

    }

    //if ([self.trustedHosts containsObject:self.trustedURL]) {

    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];

    //}

    completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);

}

而平时我们使用 AFNetworking 对 self-signed HTTPS server 进行 POST 和 GET 的时候也可以使用 NSURLConnection 进行手动添加信任操作.