以下代码是我使用以前帖子中有关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];
答案 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会崩溃。