2012-05-23 134 views
6

我试图接受NSURLConnection中的自签名证书,就像我之前的许多证书一样。问题在于,我只想接受来自我信任的证书白名单的证书。我会解决如何接受一个单一的证书。下面是我在我的NSURLConnectionDelegate这么远代码:如何接受iOS中的白名单中的自签名服务器证书?

- (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)。

回答

14

好吧,算出来。事实证明,你只需要检查服务器信任,并实际使用证书数据。

- (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, (void *)certArray, 1, 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]; 
    } 
} 
+0

如何获得'trusted.der'文件? – Hlung

+0

您可以在线查看教程以创建教程,然后将其与您的应用程序一起打包。 Google应该可以帮助其他人。 –

+0

我只是好奇,可能有一种方式,像谷歌浏览器,只是在应用程序本身自动生成。谢谢btw。 – Hlung