一般而言HTTP和HTTPS都不会遇到这个问题,只要实现NSURLConnectionDataDelegate
协议就能完成需求。但是对于自签名证书,NSURLConnection
对象无法验证服务端证书的真伪。这个时候需要动用到NSURLConnectionDelegate
协议。
具体方法是以下几个:
- - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)prote
- - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
其中
canAuthenticateAgainstProtectionSpace
如果返回No,将由系统自行处理。返回YES将会由后续的
didReceiveAuthenticationChallenge
处理。默认为No。
- - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
- {
- NSLog(@"处理证书");
- return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
- }
在
didReceiveAuthenticationChallenge
中我们要通过
challenge
的
sender
告知是否信任服务端的证书。
- - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
- {
- if (trusted) {
- [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
- } else {
- [challenge.sender cancelAuthenticationChallenge:challenge];
- }
- }
我们可以设定trusted
来判定是否信任。可以直接设置为YES来表示信任服务端。但是直接设置是不严谨的,并没有验证服务端证书的真伪。
验证证书
在连接建立后,我们可以拿到服务端的证书。要验证它的真伪需要我们用CA的证书来进行判定。
-
- NSString *certPath = [[NSBundle mainBundle] pathForResource:@"ca" ofType:@"der"];
-
- NSData *derCA = [NSData dataWithContentsOfFile:certPath];
-
-
- SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)derCA);
-
- NSArray * chain = [NSArray arrayWithObject:(__bridge id)(caRef)];
-
- caChainArrayRef = CFBridgingRetain(chain);
-
-
- SecTrustRef trust = [[challenge protectionSpace] serverTrust];
-
- SecTrustResultType trustResult = 0;
-
- int err = SecTrustSetAnchorCertificates(trust, caChainArrayRef);
- if (err == noErr) {
-
- err = SecTrustEvaluate(trust, &trustResult);
- }
- CFRelease(trust);
-
- BOOL trusted = (err == noErr) && ((trustResult == kSecTrustResultProceed)||(trustResult == kSecTrustResultConfirm) || (trustResult == kSecTrustResultUnspecified));
UIWebView中访问HTTPS
UIWebView不能处理自签名的证书,需要在它发起访问之前通过上述的方法进行证书的设置判定,之后再通过UIWebView进行访问即可通过。