我正在尝试使用NSUrlsession将服务器与SSL(.p12)客户端证书连接起来。我已成功使用NSURLConnection连接到同一台服务器。 但是凭借NSURLsession,我得到了#34;取消了#34;错误。 以下是我的设置:
-(void) loadDataFromServer{
NSURL *url=[NSURL URLWithString:@"https://domain:port/serviceName/method/parameter"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionConfiguration *sessionConfig =[NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session=[NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:Nil];
NSURLSessionDataTask *downloadTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"Data :%@",data);
NSLog(@"Response :%@",response);
NSLog(@"Error :%@",error);
if (!error) {
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;
if (httpResp.statusCode == 200) {
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:&error];
NSLog(@"Data :%@",json);
}
}
}];
[downloadTask resume];}
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler{
NSURLCredential *newCredential;
NSString *authenticationMethod = challenge.protectionSpace.authenticationMethod;
if ([authenticationMethod isEqualToString:@"NSURLAuthenticationMethodServerTrust"]) {
// Replace the user login and password as appropriate.
newCredential = [NSURLCredential credentialWithUser:@"UserName" password:@"Password" persistence:NSURLCredentialPersistenceNone];
} else if ([authenticationMethod isEqualToString:@"NSURLAuthenticationMethodClientCertificate"]) {
// load cert
NSString *path = [[NSBundle mainBundle] pathForResource:@"certificateName" ofType:@"p12"];
NSData *p12data = [NSData dataWithContentsOfFile:path];
CFDataRef inP12data = (__bridge CFDataRef)p12data;
SecIdentityRef myIdentity;
SecTrustRef myTrust;
OSStatus status = extractIdentityAndTrustCorpInv(inP12data, &myIdentity, &myTrust);
if (status == 0) {
SecCertificateRef myCertificate;
SecIdentityCopyCertificate(myIdentity, &myCertificate);
const void *certs[] = { myCertificate };
CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);
newCredential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistenceForSession];
}
}
[[challenge sender]useCredential:newCredential forAuthenticationChallenge:challenge];
completionHandler(NSURLSessionAuthChallengeUseCredential,newCredential);
}
#pragma mark -
#pragma mark Identity and Trust
- OSStatus extractIdentityAndTrustCorpInv(CFDataRef inP12data, SecIdentityRef *identity, SecTrustRef *trust)
{
OSStatus securityError = errSecSuccess;
CFStringRef password = CFSTR("CertPassword");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
securityError = SecPKCS12Import(inP12data, options, &items);
if (securityError == 0) {
CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
*identity = (SecIdentityRef)tempIdentity;
const void *tempTrust = NULL;
tempTrust = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
*trust = (SecTrustRef)tempTrust;
}
if (options) {
CFRelease(options);
}
return securityError;
}
NSLog给出以下错误:
错误:错误域= NSURLErrorDomain代码= -999"已取消" UserInfo = {NSErrorFailingURLKey = https://domain:port/serviceName/method/parameter,NSErrorFailingURLStringKey = https://domain:port/serviceName/method/parameter,NSLocalizedDescription = cancel}
任何帮助都将不胜感激。
答案 0 :(得分:1)
NSURLAuthenticationMethodServerTrust 不会按照您的想法执行操作。它用于验证服务器提供的TLS证书。如果要覆盖自签名证书,请使用它。
使用您提供的代码,您的所有HTTPS请求都将不安全(信任服务器提供的任何证书)或将失败。 IIRC,对于NSURLConnection,它是不安全的,对于NSURLSession,它失败了。
如果身份验证方法为 NSURLAuthenticationMethodHTTPBasic 或 NSURLAuthenticationMethodHTTPDigest ,则看起来该代码块实际上应该正在运行。
如果方法是 NSURLAuthenticationMethodServerTrust ,您应该告诉URL加载系统使用默认处理。
如果您出于某种原因尝试使用自签名证书,请阅读Apple网站上的Overriding SSL Chain Validation Correctly,了解如何以安全的方式进行操作。