[英]Using Client SSL Certificate from .mobileconfig within Enterprise iOS app
我们正在尝试在企业 iOS 应用程序中使用客户端 SSL 证书进行用户身份验证。
我们如何让它发挥作用? 谢谢!
概述:
您已在设备钥匙串上安装了客户端 SSL 证书。
Safari.app 和 Mail.app 可以访问此钥匙串,而 iOS 应用程序则不能。
原因是我们开发的应用程序是沙盒的,在非越狱设备中没有任何访问权限。
由于 safari 可以访问它,因此连接和验证服务器挑战没有问题。
解决方案:
将导出的 P12 文件包含在 App 包中,并参考它以找到服务器正在寻找的正确客户端证书。这实际上是一种解决方法。 硬编码是获取 P12 文件的可靠方法。
执行:
有问题的方法是NSURLConenction delegate
willSendRequestForAuthenticationChallenge
。 您需要考虑NSURLAuthenticationMethodClientCertificate
质询类型以处理服务器质询。 这是我们实现从嵌入的 P12 文件中提取正确证书身份的魔法的地方。 代码如下
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge previousFailureCount] > 0) {
//this will cause an authentication failure
[[challenge sender] cancelAuthenticationChallenge:challenge];
NSLog(@"Bad Username Or Password");
return;
}
//this is checking the server certificate
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
SecTrustResultType result;
//This takes the serverTrust object and checkes it against your keychain
SecTrustEvaluate(challenge.protectionSpace.serverTrust, &result);
//if we want to ignore invalid server for certificates, we just accept the server
if (kSPAllowInvalidServerCertificates) {
[challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge: challenge];
return;
} else if(result == kSecTrustResultProceed || result == kSecTrustResultConfirm || result == kSecTrustResultUnspecified) {
//When testing this against a trusted server I got kSecTrustResultUnspecified every time. But the other two match the description of a trusted server
[challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge: challenge];
return;
}
} else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate) {
//this handles authenticating the client certificate
/*
What we need to do here is get the certificate and an an identity so we can do this:
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:myCerts persistence:NSURLCredentialPersistencePermanent];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
It's easy to load the certificate using the code in -installCertificate
It's more difficult to get the identity.
We can get it from a .p12 file, but you need a passphrase:
*/
NSString *p12Path = [[BundleManager bundleForCurrentSkin] pathForResource:kP12FileName ofType:@"p12"];
NSData *p12Data = [[NSData alloc] initWithContentsOfFile:p12Path];
CFStringRef password = CFSTR("PASSWORD");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef p12Items;
OSStatus result = SecPKCS12Import((CFDataRef)p12Data, optionsDictionary, &p12Items);
if(result == noErr) {
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(p12Items, 0);
SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity);
SecCertificateRef certRef;
SecIdentityCopyCertificate(identityApp, &certRef);
SecCertificateRef certArray[1] = { certRef };
CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
CFRelease(certRef);
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identityApp certificates:(NSArray *)myCerts persistence:NSURLCredentialPersistencePermanent];
CFRelease(myCerts);
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
} else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodDefault || [[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodNTLM) {
// For normal authentication based on username and password. This could be NTLM or Default.
DAVCredentials *cred = _parentSession.credentials;
NSURLCredential *credential = [NSURLCredential credentialWithUser:cred.username password:cred.password persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
} else {
//If everything fails, we cancel the challenge.
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
希望这可以帮助
我创建了一个包来处理 TLS 套接字/iOS/Obj-C。 我将它连接到节点服务器,但它可能与其他人一起工作。 更重要的是,鉴于最近的 iOS 13 TLS 限制,我提供了有关正确创建证书的重要资源的链接。 我希望它可以有点帮助:
https://github.com/eamonwhiter73/IOSObjCWebSockets/tree/master
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.