AFNetworking3.0 SSL 双向证书验证(pfx p12证书格式)

来源:互联网 发布:字幕合并软件 编辑:程序博客网 时间:2024/05/29 17:11

   实际开发中使用pfx格式证书进行分发,但AFSecurityPolicy工具类不支持除.cer格式外的证书,通过了解NSURLSession网络请求,其证书验证通过此NSURLSessionDelegate协议中的

- (void)URLSession:(NSURLSession *)sessiondidReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler

进行双向验证,因此可考虑从此入手。
   AFNetworking经cocopods进行管理,如果直接对AFNetworking进行修改,不利于代码管理与分发,秉着封装使用的想法,可采用继承重写协议方法实现,既能保持AFNetworking源码完整,又可不影响其它网络协议使用。代码如下:
#import <AFNetworking/AFNetworking.h>/** * 用于pfx服务器证书校验 */@interface YKHTTPSessionManager : AFHTTPSessionManager@property (nonatomic,copy) NSString *clientPFXName;@property (nonatomic,copy) NSString *clientPFXPwd;@end
#import "YKHTTPSessionManager.h"@implementation YKHTTPSessionManager//重写方法,保持原有方案- (void)URLSession:(NSURLSession *)sessiondidReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{    NSString *authenticationMethod = challenge.protectionSpace.authenticationMethod;    //1. 服务器认证    NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;    __block NSURLCredential *credential = nil;    if ([authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {        if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {            credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];            if (credential) {                disposition = NSURLSessionAuthChallengeUseCredential;            } else {                disposition = NSURLSessionAuthChallengePerformDefaultHandling;            }        } else {            disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;        }        completionHandler(disposition,credential);    }        //2. 客户端认证    if([authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic] ||       [authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPDigest] ||       [authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]){        //失败重试3次        if([challenge previousFailureCount] == 3){            completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);                    } else {            NSURLCredential *credential = [self getCredential];            if(credential) {                completionHandler(NSURLSessionAuthChallengeUseCredential, credential);            } else {                completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);            }        }    }    }-(NSURLCredential *)getCredential{    NSString *clientPFX = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:self.clientPFXName];    NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:clientPFX];    CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;        SecIdentityRef identity = nil;    // extract the ideneity from the certificate    [self extractIdentity :inPKCS12Data :&identity :self.clientPFXPwd];        SecCertificateRef certificate = nil;    SecIdentityCopyCertificate (identity, &certificate);        const void *certs[] = {certificate};    CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);    // create a credential from the certificate and ideneity, then reply to the challenge with the credential    NSURLCredential *credentialTurs = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];    CFRelease(certArray);        return credentialTurs;}- (OSStatus)extractIdentity:(CFDataRef)inP12Data                           :(SecIdentityRef*)identity                           :(NSString*)clientPFXPassword{    OSStatus securityError = errSecSuccess;    CFStringRef password = (__bridge CFStringRef)clientPFXPassword;    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 ident = CFArrayGetValueAtIndex(items,0);        const void *tempIdentity = NULL;        tempIdentity = CFDictionaryGetValue(ident, kSecImportItemIdentity);        *identity = (SecIdentityRef)tempIdentity;            }        if (options) {        CFRelease(options);    }        return securityError;}@end

使用:

-(YKHTTPSessionManager*)afmanager{    if(!_afmanager){        _afmanager = [YKHTTPSessionManager manager];        _afmanager.responseSerializer = [AFHTTPResponseSerializer serializer];    }    return _afmanager;}if(ssl){        AFSecurityPolicy *securityPolicy =        [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];        [securityPolicy setAllowInvalidCertificates:YES];        self.afmanager.clientPFXName = @"xxx.pfx";        self.afmanager.clientPFXPwd = @"xxxx";        self.afmanager.securityPolicy = securityPolicy;    }        NSURLSessionDataTask *task = nil;    __weak typeof(YKNetworking*) weakWorking = self;    NSString *urlString = [NSString stringWithFormat:@"%@/%@",hostPath,funtionPath];    if([httpMethod isEqualToString:@"POST"]){        task = [self.afmanager POST:urlString parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {            completedBlock([weakWorking settingRequest:responseObject dataTask:task error:nil urlString:urlString params:params]);                    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {            completedBlock([weakWorking settingRequest:nil dataTask:task error:error urlString:urlString params:params]);        }];            }else{        task = [self.afmanager GET:urlString parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {            completedBlock([weakWorking settingRequest:responseObject dataTask:task error:nil urlString:urlString params:params]);                    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {            completedBlock([weakWorking settingRequest:nil dataTask:task error:error urlString:urlString params:params]);        }];    }





0 0
原创粉丝点击