我试图在NSURLConnection中接受自签名证书,正如许多人在我之前所做的那样.问题是,我只想接受我信任的证书白名单中的证书.我决心要弄清楚如何接受单一证书.这是我在NSURLConnectionDelegate中到目前为止所获得的代码:
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSString *thePath = [[NSBundle mainBundle] pathForResource:@"trusted" ofType:@"der"]; NSData *certData = [[NSData alloc] initWithContentsOfFile:thePath]; CFDataRef myCertData = (__bridge_retained CFDataRef)certData; SecCertificateRef myCert = SecCertificateCreateWithData(NULL,myCertData); SecPolicyRef myPolicy = SecPolicyCreateBasicX509(); SecCertificateRef certArray[1] = { myCert }; CFArrayRef myCerts = CFArrayCreate(NULL,(void *)certArray,1,NULL); SecTrustRef myTrust; OSStatus status = SecTrustCreateWithCertificates(myCerts,myPolicy,&myTrust); SecTrustResultType trustResult; if (status == noErr) { status = SecTrustEvaluate(myTrust,&trustResult); } BOOL trusted = NO; if (trustResult == kSecTrustResultUnspecified) { // I never get here. Instead,trustResult is always kSecTrustResultRecoverableTrustFailure trusted = YES; } if (trusted) { [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; } else { [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; } CFRelease(myTrust); CFRelease(myCerts); CFRelease(myPolicy); CFRelease(myCert); CFRelease(myCertData); } else { [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; } }
正如您在评论中看到的那样,我实际上从未获得过kSecTrustResultUnspecified,这是我期望得到的.我验证了我的证书是正确的,并且格式正确(DER).
解决方法
好吧,想通了.事实证明,您只需要检查服务器信任,并实际使用证书数据.
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { BOOL trusted = NO; if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSString *thePath = [[NSBundle mainBundle] pathForResource:@"trusted" ofType:@"der"]; NSData *certData = [[NSData alloc] initWithContentsOfFile:thePath]; CFDataRef certDataRef = (__bridge_retained CFDataRef)certData; SecCertificateRef cert = SecCertificateCreateWithData(NULL,certDataRef); SecPolicyRef policyRef = SecPolicyCreateBasicX509(); SecCertificateRef certArray[1] = { cert }; CFArrayRef certArrayRef = CFArrayCreate(NULL,NULL); SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; SecTrustSetAnchorCertificates(serverTrust,certArrayRef); SecTrustResultType trustResult; SecTrustEvaluate(serverTrust,&trustResult); trusted = (trustResult == kSecTrustResultUnspecified); CFRelease(certArrayRef); CFRelease(policyRef); CFRelease(cert); CFRelease(certDataRef); } if (trusted) { [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; } else { [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; } }