实际开发中使用pfx格式证书进行分发,但AFSecurityPolicy工具类不支持除.cer格式外的证书,通过了解NSURLSession网络请求,其证书验证通过此NSURLSessionDelegate协议中的
- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
#import
/**
* 用于pfx服务器证书校验
*/
@interface YKHTTPSessionManager : AFHTTPSessionManager
@property (nonatomic,copy) NSString *clientPFXName;
@property (nonatomic,copy) NSString *clientPFXPwd;
@end
#import "YKHTTPSessionManager.h"
@implementation YKHTTPSessionManager
//重写方法,保持原有方案
- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(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]);
}];
}