IOS HTTPS证书问题

本文节选自

https://gist.github.com/JacksonTian/5855751


一般而言HTTP和HTTPS都不会遇到这个问题,只要实现NSURLConnectionDataDelegate协议就能完成需求。但是对于自签名证书,NSURLConnection对象无法验证服务端证书的真伪。这个时候需要动用到NSURLConnectionDelegate协议。

具体方法是以下几个:

[objc]  view plain copy
  1. - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)prote  
  2. - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;  

其中 canAuthenticateAgainstProtectionSpace 如果返回No,将由系统自行处理。返回YES将会由后续的 didReceiveAuthenticationChallenge 处理。默认为No。

[objc]  view plain copy
  1. - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace  
  2. {  
  3.     NSLog(@"处理证书");  
  4.     return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];  
  5. }  
didReceiveAuthenticationChallenge 中我们要通过 challenge sender 告知是否信任服务端的证书。
[objc]  view plain copy
  1. - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge  
  2. {  
  3.     if (trusted) {  
  4.         [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];  
  5.     } else {  
  6.         [challenge.sender cancelAuthenticationChallenge:challenge];  
  7.     }  
  8. }  

我们可以设定trusted来判定是否信任。可以直接设置为YES来表示信任服务端。但是直接设置是不严谨的,并没有验证服务端证书的真伪。

验证证书

在连接建立后,我们可以拿到服务端的证书。要验证它的真伪需要我们用CA的证书来进行判定。

[objc]  view plain copy
  1. // 获取der格式CA证书路径  
  2. NSString *certPath = [[NSBundle mainBundle] pathForResource:@"ca" ofType:@"der"];  
  3. // 提取二进制内容  
  4. NSData *derCA = [NSData dataWithContentsOfFile:certPath];  
  5.   
  6. // 根据二进制内容提取证书信息  
  7. SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)derCA);  
  8. // 形成钥匙链  
  9. NSArray * chain = [NSArray arrayWithObject:(__bridge id)(caRef)];  
  10.   
  11. caChainArrayRef = CFBridgingRetain(chain);  
  12.   
  13. // 取出服务器证书  
  14. SecTrustRef trust = [[challenge protectionSpace] serverTrust];  
  15.   
  16. SecTrustResultType trustResult = 0;  
  17. // 设置为我们自有的CA证书钥匙连  
  18. int err = SecTrustSetAnchorCertificates(trust, caChainArrayRef);  
  19. if (err == noErr) {  
  20.     // 用CA证书验证服务器证书  
  21.     err = SecTrustEvaluate(trust, &trustResult);  
  22. }  
  23. CFRelease(trust);  
  24. // 检查结果  
  25. BOOL trusted = (err == noErr) && ((trustResult == kSecTrustResultProceed)||(trustResult == kSecTrustResultConfirm) || (trustResult == kSecTrustResultUnspecified));  

UIWebView中访问HTTPS

UIWebView不能处理自签名的证书,需要在它发起访问之前通过上述的方法进行证书的设置判定,之后再通过UIWebView进行访问即可通过。

你可能感兴趣的:(网络)