gpt4 book ai didi

ios - 在 Enterprise iOS 应用程序中使用来自 .mobileconfig 的客户端 SSL 证书

转载 作者:技术小花猫 更新时间:2023-10-29 10:37:25 28 4
gpt4 key购买 nike

我们正在尝试使用客户端 SSL 证书在企业 iOS 应用程序中进行用户身份验证。

  • 我们可以在服务器上生成客户端ssl证书
  • 用户可以通过 .mobileconfig 安装它
  • 在 Safari 中对 Web 服务器的身份验证使用已安装的证书。
  • 从 iOS 应用程序内部发出 http 请求失败(未使用证书)。

我们如何让它发挥作用?谢谢!

最佳答案

概述:

您已经在设备钥匙串(keychain)上安装了客户端 SSL 证书。

Safari.app 和 Mail.app 可以访问这个钥匙串(keychain),而 iOS 应用程序不能。

原因是我们开发的应用程序是沙盒的,在未越狱的设备上没有任何访问权限。

由于 safari 可以访问它,因此它可以轻松连接并针对服务器质询进行身份验证。

解决方案:

将导出的 P12 文件包含在应用程序包中,并引用它以找到服务器正在寻找的正确客户端证书。这实际上是一种解决方法。硬编码是抓取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];
}
}

引用: Ref1 , Ref2 , Ref3

希望对你有帮助

关于ios - 在 Enterprise iOS 应用程序中使用来自 .mobileconfig 的客户端 SSL 证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29754785/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com