使用客户端证书身份验证时,为什么我一直收到NSURLErrorDomain Code = -1206?

时间:2013-05-04 05:59:12

标签: ios ssl-certificate x509certificate authentication

以下代码是我使用以前帖子中有关ios客户端证书身份验证的代码。每个人说这都行,但为什么它对我有用?!?!

我一直收到以下错误:

connection didFailWithError: Error Domain=NSURLErrorDomain Code=-1206 "The server “www.mywebsite.com” requires a client certificate.

我在stackoverflow上至少关注了4个关于同一主题的帖子,在其他类似网站上关注了2个帖子。他们都说同样的话,除非它不起作用。

我知道我的 PKCS12 文件有效,因为我通过电子邮件将其发送到我的ipad,我将其安装在ipad钥匙串上,并且我可以使用Safari访问和授权使用证书身份。只是当我尝试在第三方应用中使用NSURLConnection时,它拒绝允许我这样做。

欢迎任何建议,我觉得我已经筋疲力尽了。


    // Download PKCS12 Cert from my FTP server.

    NSString *stringURL = @"ftp://user:password@myipaddress/myclientId.p12";        
    NSString* webStringURL = [stringURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL  *url = [NSURL URLWithString:webStringURL];
    NSData *p12Data = [NSData dataWithContentsOfURL:url];


    if ( p12Data )
    {   
        CFDataRef inP12data = (__bridge CFDataRef)p12Data;

        SecIdentityRef myIdentity;
        SecTrustRef myTrust;
        OSStatus errMsg = NULL;

        // This is the same function that has been reposted in all the other posts about ios client certification authentication.  So i'm not going to repost that.
        errMsg = extractIdentityAndTrust(inP12data, &myIdentity, &myTrust);

        SecCertificateRef myCertificate;
        SecIdentityCopyCertificate(myIdentity, &myCertificate);

        const void *certs[] = { myCertificate };

        CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);

        NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistenceNone];

        [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];

2 个答案:

答案 0 :(得分:2)

错误就在这条线上。第二个参数需要设置为“nil”

    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistenceNone];

更改为:

    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:nil persistence:NSURLCredentialPersistenceNone];

答案 1 :(得分:1)

您的.p12可能包含中间证书,您的服务器需要这些中间证书。

您可以使用wireshark验证您的代码将以身份的重复证书发送,但客户端证书响应中没有中间证书。

如果出现这种情况,您还要从p12中提取证书并传递以创建NSURLCredentials:

int count = SecTrustGetCertificateCount(myTrust);
NSMutableArray* myCertificates = nil;
if (count > 1) {
    myCertificates = [NSMutableArray arrayWithCapacity:SecTrustGetCertificateCount(myTrust)];
    for (int i = 1; i < count; ++i) {  // remove the leaf cert
         [certs addObject:(id)SecTrustGetCertificateAtIndex(myTrust, i)];
    }
}
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:myCertificates persistence:NSURLCredentialPersistenceNone];

另外,将nil传递给NSURLCredential不应该破坏任何代码。看Apple的样本: https://developer.apple.com/library/ios/documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html。但是将空数组@ []传递给NSURLCredential会崩溃。