Dav*_* S. 7 ssl https openssl activesync ios
我正在尝试在我正在开发的ActiveSync客户端中实现证书身份验证.使用证书身份验证的代码可能有效,但截至目前服务器,或者更准确地说,iOS库对服务器响应的解释似乎对我不正确.这是我的代码:
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
NSString *authenticationMethod = [protectionSpace authenticationMethod];
if ([authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate])
{
NSURLCredential* credential = [ self buildCredentialClientCert];
if ( credential == nil )
{
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
else
{
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
}
else if ([authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
.... // do other stuff
Run Code Online (Sandbox Code Playgroud)
问题是,即使我知道服务器支持客户端证书身份验证,当我设置断点时authenticationMethod,总是设置为NSURLAuthenticationMethodServerTrust.
原始HTTPS服务器响应包含以下内容:
错误代码:403禁止.该页面需要客户端证书作为身份验证过程的一部分.如果您使用的是智能卡,则需要插入智能卡以选择合适的证书.否则,请与服务器管理员联系.(12213)
我的问题是,什么决定如果认证挑战是NSURLAuthenticationMethodServerTrust对NSURLAuthenticationMethodClientCertificate?
Dav*_* S. 13
既然没有人回答这个问题,我最终确实达成了一个有效的解决方案,就在这里.
服务器信任不是从服务器到客户端的挑战,它是客户端验证服务器提供的信任的机会.考虑到这一点,下面的代码不会验证信任,但它可以.
通常,您获得NSURLAuthenticationMethodServerTrust,然后获得NSURLAuthenticationMethodClientCertificate.它不是 - 或者.这是工作代码.
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
NSString *authenticationMethod = [protectionSpace authenticationMethod];
if ([authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate] && self.accountCertKeychainRef != nil)
{
SecIdentityRef identity = [KeychainUtilities retrieveIdentityWithPersistentRef:self.accountCertKeychainRef];
NSURLCredential* credential = [CertificateUtilities getCredentialFromCert:identity];
if ( credential == nil )
{
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
else
{
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
}
else if ([authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
}
else if ([authenticationMethod isEqualToString:NSURLAuthenticationMethodNTLM] || [authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic])
{
self.lastProtSpace = [challenge protectionSpace];
if ([challenge previousFailureCount] > 2)
{
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
else
{
[[challenge sender] useCredential:[self buildCredential] forAuthenticationChallenge:challenge];
}
}
else
{
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
Run Code Online (Sandbox Code Playgroud)
对于下面的问题,这里是你如何获得身份:
+ (SecIdentityRef)copyIdentityAndTrustWithCertData:(CFDataRef)inPKCS12Data password:(CFStringRef)keyPassword
{
SecIdentityRef extractedIdentity = nil;
OSStatus securityError = errSecSuccess;
const void *keys[] = {kSecImportExportPassphrase};
const void *values[] = {keyPassword};
CFDictionaryRef optionsDictionary = NULL;
optionsDictionary = CFDictionaryCreate(NULL, keys, values, (keyPassword ? 1 : 0), NULL, NULL);
CFArrayRef items = NULL;
securityError = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);
if (securityError == errSecSuccess) {
CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
// get identity from dictionary
extractedIdentity = (SecIdentityRef)CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
CFRetain(extractedIdentity);
}
if (optionsDictionary) {
CFRelease(optionsDictionary);
}
if (items) {
CFRelease(items);
}
return extractedIdentity;
}
Run Code Online (Sandbox Code Playgroud)
对于那些感兴趣的人,这里是getCredentialForCert:
+ (NSURLCredential *)getCredentialFromCert:(SecIdentityRef)identity
{
SecCertificateRef certificateRef = NULL;
SecIdentityCopyCertificate(identity, &certificateRef);
NSArray *certificateArray = [[NSArray alloc] initWithObjects:(__bridge_transfer id)(certificateRef), nil];
NSURLCredentialPersistence persistence = NSURLCredentialPersistenceForSession;
NSURLCredential *credential = [[NSURLCredential alloc] initWithIdentity:identity
certificates:certificateArray
persistence:persistence];
return credential;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4437 次 |
| 最近记录: |