6

我正在尝试在 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)。

4

1 回答 1

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];
    }
}
于 2012-05-23T21:39:55.533 回答