iOS中相互身份验证的等效代码是什么?

时间:2015-10-29 04:26:32

标签: ios node.js certificate ssl-certificate client-certificates

我正在尝试对需要相互身份验证的服务器进行API调用。 使用NodeJS和请求库,我可以使用以下代码

来访问API
var keyFile = '/Users/username/Documents/Certificates/example-key.pem';
var certificateFile = '/Users/username/Documents/Certificates/cert.pem';
var options = {
    uri: 'https://myserver.com/apiOne',
    key: fs.readFileSync(keyFile),
    cert: fs.readFileSync(certificateFile),
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Authorization': 'Basic ' + new Buffer(userId + ':' + password).toString('base64')
    },
    body: data //JSON body
};
request.postAsync(options)
    .spread(function (response, body) {
        res.status(200).json(JSON.parse(body));
    })
    .catch(function (err) {
        res.status(400).send(err);
    })

如何从iOS应用中获得相同的API? 我使用以下代码,但服务器没有响应

func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential!) -> Void) {
    if challenge.protectionSpace.authenticationMethod == "NSURLAuthenticationMethodServerTrust" {
        let credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)

NodeJS代码中的密钥和证书是什么意思?我如何在iOS中传递它们?

1 个答案:

答案 0 :(得分:1)

首先,您需要将密钥和证书转换为p12文件。 为此,请运行以下命令

openssl pkcs12 -export -out new.p12 -inkey example-key.pem -in cert.pem

它还会提示您输入密码。在以下代码中使用此创建的p12和密码的路径

#pragma mark - Get Identity
- (SecIdentityRef)getIdentity {
    SecIdentityRef identity = nil;
    CFStringRef password = (__bridge CFStringRef)certPassword; //the password that you entered while creating the p12 file
    const void *keys[] = { kSecImportExportPassphrase };
    const void *values[] = { password };
    CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
    NSData *certData = [NSData dataWithContentsOfFile:certFilePath]; //the path to the p12 file. You can get this from bundle
    CFArrayRef items = CFArrayCreate(nil, 0, 0, nil);
    OSStatus status = SecPKCS12Import((__bridge CFDataRef)(certData), options, &items);
    CFRelease(options);
    CFRelease(password);
    if (status == errSecSuccess) {
        NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items));
        CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
        identity = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
    } else {
        NSLog(@"Error opening Certificate.");
    }
    return identity;
}

#pragma mark - Get Certificates
- (CFArrayRef)getCertificates:(SecIdentityRef) identity {
    SecCertificateRef certificate = nil;
    SecIdentityCopyCertificate(identity, &certificate);
    SecCertificateRef certs[1] = { certificate };
    CFArrayRef array = CFArrayCreate(NULL, (const void **) certs, 1, NULL);
    return array;
}

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {
    NSString *authMethod = challenge.protectionSpace.authenticationMethod;
    NSLog(@"auth method %@", authMethod);
    if ([authMethod isEqualToString:@"NSURLAuthenticationMethodServerTrust"] || [authMethod isEqualToString:@"NSURLAuthenticationMethodClientCertificate"]) {
        SecIdentityRef identity = [self getIdentity];  // Go get a SecIdentityRef
        CFArrayRef certs = [self getCertificates:identity]; // Get an array of certificates
        NSArray *myArray = (__bridge NSArray *)certs;

        NSURLCredential *newCredential = [NSURLCredential credentialWithIdentity:identity certificates:myArray persistence:NSURLCredentialPersistencePermanent];
        [challenge.sender useCredential:newCredential forAuthenticationChallenge:challenge];
        completionHandler(NSURLSessionAuthChallengeUseCredential, newCredential);
    }
}