网上找到方法把证书加到bundle reosource里面:
然后使用下面的代码验证证书:
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
// 直接验证服务器是否被认证(serverTrust),这种方式直接忽略证书验证,直接建立连接,但不能过滤其它URL连接,可以理解为一种折衷的处理方式,实际上并不安全,因此不推荐。
// SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
// return [[challenge sender] useCredential: [NSURLCredential credentialForTrust: serverTrust]
// forAuthenticationChallenge: challenge];
if ([[[challenge protectionSpace] authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust]) {
do
{
SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
NSCAssert(serverTrust != nil, @"serverTrust is nil");
if(nil == serverTrust)
break; /* failed */
/**
* 导入多张CA证书(Certification Authority,支持SSL证书以及自签名的CA)
*/
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"xxx" ofType:@"der"];//自签名证书
NSData *caCert = [NSData dataWithContentsOfFile:cerPath];
// NSString *cerPath2 = [[NSBundle mainBundle] pathForResource:@"apple" ofType:@"cer"];//SSL证书
// NSData *caCert2 = [NSData dataWithContentsOfFile:cerPath2];
if(nil == caCert)
break; /* failed */
SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert);
if(nil == caRef)
break; /* failed */
NSArray *caArray = @[(__bridge id)(caRef)];
if(nil == caArray)
break; /* failed */
OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
SecTrustSetAnchorCertificatesOnly(serverTrust,false);
if(!(errSecSuccess == status))
break; /* failed */
SecTrustResultType result = -1;
status = SecTrustEvaluate(serverTrust, &result);
if(!(errSecSuccess == status))
break; /* failed */
NSLog(@"stutas:%d",(int)status);
NSLog(@"Result: %d", result);
BOOL allowConnect = (result == kSecTrustResultUnspecified) || (result == kSecTrustResultProceed);
if (allowConnect) {
NSLog(@"success");
}else {
NSLog(@"error");
}
if(!allowConnect)
{
break; /* failed */
}
#if 0
/* Treat kSecTrustResultConfirm and kSecTrustResultRecoverableTrustFailure as success */
/* since the user will likely tap-through to see the dancing bunnies */
if(result == kSecTrustResultDeny || result == kSecTrustResultFatalTrustFailure || result == kSecTrustResultOtherError)
{
break; /* failed to trust cert (good in this case) */
}
#endif
// The only good exit point
return [[challenge sender] useCredential: [NSURLCredential credentialForTrust: serverTrust]
forAuthenticationChallenge: challenge];
} while(0);
}
return [[challenge sender] cancelAuthenticationChallenge: challenge];
}
有个问题就是不能使用.cer的证书,否则SecCertificateCreateWithData会返回nil,我就是被这个坑了两天。。。
原因是:The newly created certificate object. Call the CFRelease
function to release this object when you are finished with it. Returns NULL
if the data passed in the data
parameter is not a valid DER-encoded X.509 certificate.
可以使用:
openssl x509 -in xxx.cer -outform der -out xxx.der来转
这是我参考的文章:http://www.jianshu.com/p/6b9c8bd5005a