iOS适配HTTPS 双向认证 (AFNetworking)

static AFHTTPRequestOperationManager *rom =nil;

我是封装了一下 Sharemanger, 

rom.securityPolicy = [self customSecurityPolicy]; //设置HTTPS的验证类 

 

+ (AFSecurityPolicy*)customSecurityPolicy

{
    
    // /先导入证书
    在这加证书,一般情况适用于单项认证
//    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"igoda" ofType:@"cer"];//证书的路径
//    
//    NSData *certData = [NSData dataWithContentsOfFile:cerPath];
//    if (ISNULL(certData)) {
//        return nil;
//    }
    // AFSSLPinningModeCertificate 使用证书验证模式
    
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
    
    // allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO
    
    // 如果是需要验证自建证书,需要设置为YES
    
    securityPolicy.allowInvalidCertificates = YES;
    
    //validatesDomainName 是否需要验证域名,默认为YES;
    
    //假如证书的域名与你请求的域名不一致,需把该项设置为NO;如设成NO的话,即服务器使用其他可信任机构颁发的证书,也可以建立连接,这个非常危险,建议打开。
    
    //置为NO,主要用于这种情况:客户端请求的是子域名,而证书上的是另外一个域名。因为SSL证书上的域名是独立的,假如证书上注册的域名是www.google.com,那么mail.google.com是无法验证通过的;当然,有钱可以注册通配符的域名*.google.com,但这个还是比较贵的。
    
    //如置为NO,建议自己添加对应域名的校验逻辑。
    
    securityPolicy.validatesDomainName = NO;
    
//    securityPolicy.pinnedCertificates = @[certData];
    
    return securityPolicy;
    
}

然后在  

AFURLConnectionOperation.m  中加方法

- (OSStatus)extractIdentity:(CFDataRef)inP12Data toIdentity:(SecIdentityRef*)identity {
    
    OSStatus securityError = errSecSuccess;
    
    
    
    CFStringRef password = CFSTR("igoda2016");
    
    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;
    
}

然后将验证HTTPS的代理方法 

- (void)connection:(NSURLConnection *)connection

willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge  内容替换一下,要加自己证书  和证书的密码

方法内容全部替换为 :

 NSString *thePath = [[NSBundle mainBundle] pathForResource:@"goda" ofType:@"p12"];
    //倒入证书       NSLog(@"thePath===========%@",thePath);
    NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
    CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
    
    SecIdentityRef identity = NULL;
    // extract the ideneity from the certificate
    [self extractIdentity :inPKCS12Data toIdentity:&identity];
    
    SecCertificateRef certificate = NULL;
    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
    //NSLog(@"identity=========%@",identity);
    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:nil persistence:NSURLCredentialPersistencePermanent];
    
    //           credential = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];
    
    [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];

到这就大功告成

 用抓包工具 Charles试试:

原文地址:https://www.cnblogs.com/KingQiangzi/p/5820884.html