没有任何信息的NSURLCredential崩溃 - 基于证书的身份验证

时间:2013-06-14 04:06:14

标签: ios nsurlcredential

在我的应用中,我需要根据证书对用户进行身份验证。 我就是这样做的 1.首先,我将证书导出到沙箱中。 2.然后我从证书中提取SecIdentityRef,将其添加到钥匙串,然后从沙箱中删除证书。 3.当我实际将此身份传递给NSURL连接的身份验证质询时,应用程序只会在没有提供任何有意义信息的情况下崩溃。

以下是所有相关的代码段

//Exporting the certificate into the app and extracting the identity from it

- (void)importCertificateIntoKeychain:(NSString *)Password
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"Certificates"];
    NSString *certFolderName = [[[[NSUserDefaults standardUserDefaults] objectForKey:@"CertificatePath"] lastPathComponent]stringByDeletingPathExtension];
    NSString *path = [NSString stringWithFormat:@"%@/%@",dataPath,certFolderName];
    NSArray*array = [[NSFileManager defaultManager]
                     contentsOfDirectoryAtPath:
                     path
                     error:nil];
    NSString *thePath;
    NSString *fileName;
    for (int i=0;i<array.count;i++) {
        if ([[array objectAtIndex:i]hasSuffix:@".pfx"]) {
            fileName= [array objectAtIndex:i];
            thePath = [NSString stringWithFormat:@"%@/%@",path,fileName];
        }
    }

    SecIdentityRef identityApp = nil;

    NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
    CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
    NSString *pwd = Password;
    CFStringRef password = (CFStringRef)CFBridgingRetain(pwd);
    const void *keys[] = { kSecImportExportPassphrase };
    const void *values[] = { password };
    CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items);
    CFRelease(options);
    CFRelease(password);
    if (securityError == errSecSuccess) {
        NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items));
        CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
        identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
        SecCertificateRef certificate = NULL;
        SecIdentityCopyCertificate (identityApp, &certificate);

       OSStatus status = errSecSuccess;

        CFTypeRef persistent_ref = NULL;
        const void *keys[] = { kSecReturnPersistentRef, kSecValueRef };
        const void *values[] = { kCFBooleanTrue, identityApp };
        CFDictionaryRef dict = CFDictionaryCreate(NULL, keys, values,
                                                             2, NULL, NULL);
        status = SecItemAdd(dict, &persistent_ref);
        NSLog(@"Status %ld",status);

        if (dict)
        CFRelease(dict);
        [Utils deleteCertificateFromInboxFolder];
    } else {
        NSLog(@"Error opening Certificate.");
        [Utils displayAlertWithTitle:@"Wrong Password" andMessage:@"Error opening certificate"];
    }
}

在身份验证质询中传递此凭据

if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate)
    {
        fprintf(stderr, "identities:\n");
        fprintf(stderr, "certificates:\n");
        NSLog(@"NSURLAuthenticationMethodClientCertificate");

        SecIdentityRef identity;
        identity = (__bridge SecIdentityRef)([self _dumpCredentialsOfSecClass:kSecClassIdentity printSelector:@selector(_printIdentity:attributes:)]);
        SecCertificateRef certificate1 = NULL;
        OSStatus *stat = SecIdentityCopyCertificate (identity, &certificate1);
        //const void *certs[] = {certificate1};

        SecCertificateRef certArray[1] = { certificate1 };
        CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
        CFRelease(certificate1);
        NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity
                                                                 certificates:(__bridge NSArray *)myCerts
                                                                  persistence:NSURLCredentialPersistencePermanent];
        CFRelease(myCerts);

//        CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
//        
//        NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)certArray persistence:NSURLCredentialPersistenceNone];
        [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
}

将此凭据传递给NSURLChallenge发件人后,应用程序崩溃。

enter image description here

非常感谢任何帮助!!!

2 个答案:

答案 0 :(得分:0)

您是否尝试为项目启用zombie对象?它可以帮助您找出问题所在。

答案 1 :(得分:0)

好的,我好像修好了。

已更改

 identity = (__bridge SecIdentityRef)([self _dumpCredentialsOfSecClass:kSecClassIdentity printSelector:@selector(_printIdentity:attributes:)]);

identity = (SecIdentityRef)CFBridgingRetain([self _dumpCredentialsOfSecClass:kSecClassIdentity printSelector:@selector(_printIdentity:attributes:)]);

希望这有助于某人