SSL身份验证AFNetworking 2.x

时间:2015-07-02 10:59:24

标签: ios objective-c authentication ssl ssl-certificate

我想使用AFNetworking 2.0实现带证书的客户端SSL身份验证。

我已尝试过以下代码,但收到错误 -

Domain = NSURLErrorDomain Code = -1206“服务器”abc.abc.com“需要客户端证书。”

NSMutableURLRequest *request;
request = [reqSerializer requestWithMethod:method URLString:[actionURL  absoluteString] parameters:nil error:nil];
AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init];
[securityPolicy setAllowInvalidCertificates:kAllowsInvalidSSLCertificate];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFHTTPResponseSerializer serializer];
[operation setSecurityPolicy:securityPolicy];
[operation setWillSendRequestForAuthenticationChallengeBlock:^(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge) {
if ([challenge previousFailureCount] > 0) {
   //this will cause an authentication failure
   [[challenge sender] cancelAuthenticationChallenge:challenge];
   NSLog(@"Bad Username Or Password");
   return;
}
//this is checking the server certificate
if ([challenge.protectionSpace.authenticationMethod     isEqualToString:NSURLAuthenticationMethodServerTrust]) {
   SecTrustResultType result;
   //This takes the serverTrust object and checkes it against your keychain
SecTrustEvaluate(challenge.protectionSpace.serverTrust, &result);

//if we want to ignore invalid server for certificates, we just accept the server
if (kAllowsInvalidSSLCertificate) {
    [challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge: challenge];
    return;
} else if(result == kSecTrustResultProceed || result == kSecTrustResultUnspecified) {
    //When testing this against a trusted server I got kSecTrustResultUnspecified every time. But the other two match the description of a trusted server
    [challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge: challenge];
    return;
}
}else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate) {
//this handles authenticating the client certificate

/*
 What we need to do here is get the certificate and an an identity so we can do this:
 NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:myCerts persistence:NSURLCredentialPersistencePermanent];
 [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];

 It's easy to load the certificate using the code in -installCertificate
 It's more difficult to get the identity.
 We can get it from a .p12 file, but you need a passphrase:
 */

NSData *p12Data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cert" ofType:@"p12"]];

CFStringRef password = CFSTR("YOURPASSPHRASE");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef p12Items;

OSStatus result = SecPKCS12Import((__bridge CFDataRef)p12Data, optionsDictionary, &p12Items);

if(result == noErr) {
    CFDictionaryRef identityDict = CFArrayGetValueAtIndex(p12Items, 0);
    SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity);

    SecCertificateRef certRef;
    SecIdentityCopyCertificate(identityApp, &certRef);

    SecCertificateRef certArray[1] = { certRef };
    CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
    CFRelease(certRef);

    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identityApp certificates:(__bridge NSArray *)myCerts persistence:NSURLCredentialPersistencePermanent];
    CFRelease(myCerts);

    [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
} else {
    [[challenge sender] cancelAuthenticationChallenge:challenge];
}
} else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodDefault || [[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodNTLM) {

// For normal authentication based on username and password. This could be NTLM or Default.
/*
 DAVCredentials *cred = _parentSession.credentials;
 NSURLCredential *credential = [NSURLCredential credentialWithUser:cred.username password:cred.password persistence:NSURLCredentialPersistenceForSession];
 [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
 */

NSLog(@"BASIC AUTHENTICATION");

} else {
//If everything fails, we cancel the challenge.
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}];

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

NSLog(@"Success");

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {

NSLog(@"Failure");

}];

[[NSOperationQueue mainQueue] addOperation:operation];

运行此代码之前是否需要在设备上安装任何证书?

请指导。感谢

1 个答案:

答案 0 :(得分:0)

NSData *p12Data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cert" ofType:@"p12"]];

YES。这行代码从主包中读取名为cert.p12的证书。