NSURLCredentialStorage和客户端证书身份验证

时间:2010-11-12 12:59:29

标签: iphone objective-c cocoa-touch https nsurlcredential

根据我在MPMoviewPlayerController的文档中看到的,NSURLCredentialStorage可以设置为NSURLConnection身份验证挑战的替代方法(这对于从URL加载资源但是抽象NSURLConnection并且不提供委托的更高级别类非常有用处理身份验证挑战)。这似乎类似于在浏览器中安装证书,并在某个地址需要时自动选择所需的证书。

为了测试这一点,我已经设置了自己的证书颁发机构,服务器证书和客户端证书(.p12文件)。我已经设置了一个https服务器,并使用浏览器从一台单独的计算机上成功测试了客户端证书。

现在我需要在我的iPhone应用程序中集成证书。

我已经捆绑了p12文件,在应用程序启动时,我这样做了:

NSString *thePath = [[NSBundle mainBundle] pathForResource:@"clientside" ofType:@"p12"];
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data = (CFDataRef)PKCS12Data;    
SecIdentityRef identity;
SecTrustRef trust;
extractIdentityAndTrust(inPKCS12Data, &identity, &trust);

SecCertificateRef certificate = NULL;
SecIdentityCopyCertificate (identity, &certificate); 

const void *certs[] = {certificate};
CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);

NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:(NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];

NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
                                         initWithHost: @"myhostname"
                                         port: 443
                                         protocol: @"https"
                                         realm: nil
                                         authenticationMethod: NSURLAuthenticationMethodClientCertificate];

[[NSURLCredentialStorage sharedCredentialStorage]
 setDefaultCredential: credential
 forProtectionSpace: protectionSpace];

只需从“iOS的证书,密钥和信任服务任务”文档页面复制extractIdentityAndTrust函数(我只是用自己的密码替换了证书密码)。

从我可以告诉我的身份和证书很好地加载。如果我在控制台中打印NSURLCredential对象,我得到这样的结果:<NSURLCredential: 0x140ea0>: (null)(我不知道这是不是一个好兆头。)

然而,当我执行setDefaultCredential时,应用程序崩溃而没有提供太多信息。

stacktrace看起来像这样:

#0  0x350a41c8 in CFHash
#1  0x3515180c in __CFBasicHashStandardHashKey
#2  0x351534e4 in ___CFBasicHashFindBucket_Linear
#3  0x350a4000 in CFBasicHashFindBucket
#4  0x350a3ecc in CFDictionaryGetValue
#5  0x344a0df2 in URLCredentialStorage::setDefaultCredentialForProtectionSpace
#6  0x3446a5aa in CFURLCredentialStorageSetDefaultCredentialForProtectionSpace
#7  0x339ec79e in -[NSURLCredentialStorage setDefaultCredential:forProtectionSpace:]
#8  0x00002612 in -[AVPlayerExampleViewController awakeFromNib] at AVPlayerExampleViewController.m:84

在我看来,有些东西没有在凭证中设置。

关于如何解决这个问题的任何想法?

编辑:

仅用于测试我通过打开Mail中的文件在iPhone上安装了证书。我可以通过Safari访问https页面,但不能通过我的应用程序访问。

唯一可行的是,如果我打开NSURLConnection到受保护域上的任何资源,响应didReceiveAuthenticationChallenge(我在上面的代码中加载我的凭据,只有我直接发送给N​​SURLAuthenticationChallenge的发件人)然后使用更高级别的课程访问我真正需要的东西。

1 个答案:

答案 0 :(得分:4)

NSURLCredentialStorage仅适用于用户名&amp ;;这似乎是一个众所周知的问题。密码NSURLCredentials(不支持证书)。不幸的是,文档没有提到这一点。