1

我正在尝试对需要相互认证的服务器进行API调用。 使用和的NodeJS请求库我可以用下面的代码什么是iOS中相互验证的等效代码?

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打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中传递它们?

+0

我没有使用此推送通知。我只是想做一个需要相互认证的API调用。 – vivek241

回答

1

首先,您需要将key和cert转换为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); 
    } 
} 
相关问题