博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AFNetworking3.0 Https P12证书
阅读量:5794 次
发布时间:2019-06-18

本文共 5712 字,大约阅读时间需要 19 分钟。

 

最近服务器由原来的ice中间件改为https。方便了和服务器交互时不用自己aes加密了。

 

 -之前服务器人员和我(IOS)都没有使用过https,所以https跑不通很难说是服务器没有配置好还是IOS这边网络没有写好。

 -开始服务器提供了两个证书(自签名)。 一个.cer一个p12.

导入AFNetworking 之后按照其他资料提供的方法很简单。

1 NSString *urlString = @"https://xxxxx网址"; 2 NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"https" ofType:@"cer"];  //获取cer证书 3 NSData * certData =[NSData dataWithContentsOfFile:cerPath]; 4 NSSet * certSet = [[NSSet alloc] initWithObjects:certData, nil]; 5 AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; //采用证书验证模式 6 // 是否允许,NO-- 不允许无效的证书 YES-- 允许无效的证书(因为用的是自签名证书这里设置为YES,没有经过CA认证) 7 [securityPolicy setAllowInvalidCertificates:YES]; 8 // 设置证书 9 [securityPolicy setPinnedCertificates:certSet];10 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];11 manager.securityPolicy = securityPolicy;12 manager.responseSerializer = [AFHTTPResponseSerializer serializer];13 // request 这里开始GET请求14 [manager GET:urlString parameters:nil progress:^(NSProgress * progress){15 } success:^(NSURLSessionDataTask *task, id responseObject) {16     NSLog(@"OK === %@",array); //请求成功17 } failure:^(NSURLSessionDataTask *task, NSError *error) {18     NSLog(@"error ==%@",error.description); //请求失败19 }];

 

 

  -经过我一番研究,太TM简单了啊添加几个参数就行了。

  -谁知道按照这样怎么也跑不通。调试了半天,都跑到afnetworking源码里面去查了,好像查出来证书验证通过不了。AFSecurityPolicy.h这个文件里面的 AFServerTrustIsValid方法就是通过不了,里面有个枚举值

代表证书验证的结果

typedef uint32_t SecTrustResultType;

enum {
    kSecTrustResultInvalid = 0,
    kSecTrustResultProceed = 1,
    kSecTrustResultConfirm SEC_DEPRECATED_ATTRIBUTE = 2,
    kSecTrustResultDeny = 3,
    kSecTrustResultUnspecified = 4,
    kSecTrustResultRecoverableTrustFailure = 5,
    kSecTrustResultFatalTrustFailure = 6,
    kSecTrustResultOtherError = 7
};

具体枚举值什么意思直接百度就能搜出来。验证结果一直是kSecTrustResultRecoverableTrustFailure,5.意思就是证书验证失败。

  -开始怀疑服务器给的.cer证书有问题。

  -查了几天资料,找到一个只用p12证书的资料。(因为搜索资料时好多人说了证书的问题,所以怀疑和cer证书转换的格式或者编码有关,所以决定用原始的p12证书)

 

  -结果用原始的p12证书和原生的网络跑通了。用afnetworking的话资料都是用了cer,加上cer证书就跑不通。本来决定用原生网络,后来又要封装各种post啊什么的太麻烦了,所以去研究afnetworking和p12证书了。

 

 

  -最后解决。

  -afnetworking的AFURLSessionManager.m类里面的方法

- (void)URLSession:(NSURLSession *)sessiondidReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler{}

afnetworking源码里面这个方法只有一行代码,把它替换成

- (void)URLSession:(NSURLSession *)sessiondidReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler{    NSString *method = challenge.protectionSpace.authenticationMethod;    NSLog(@">>>>1 %@", method);        if([method isEqualToString:NSURLAuthenticationMethodServerTrust]){                NSString *host = challenge.protectionSpace.host;        NSLog(@">>>>2 %@", host);                NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];        completionHandler(NSURLSessionAuthChallengeUseCredential, credential);        return;    } else if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]) {                NSString *thePath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];        NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];        CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain(PKCS12Data);        SecIdentityRef identity;                                // 读取p12证书中的内容        OSStatus result = [self extractP12Data:inPKCS12Data toIdentity:&identity];                        if(result != errSecSuccess){            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);            return;        }                        SecCertificateRef certificate = NULL;        SecIdentityCopyCertificate(identity, &certificate);                const void *certs[] = {certificate};        CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);                NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:(NSArray*)CFBridgingRelease(certArray) persistence:NSURLCredentialPersistencePermanent];                completionHandler(NSURLSessionAuthChallengeUseCredential, credential);    }}

这个是收到验证证书时候的回调。

 

再在这个类里面添加一个方法

-(OSStatus) extractP12Data:(CFDataRef)inP12Data toIdentity:(SecIdentityRef*)identity {

    
    OSStatus securityError = errSecSuccess;
    
    CFStringRef password = CFSTR("yaoguang123");
    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 = (CFDictionaryRef)CFArrayGetValueAtIndex(items,0);
        const void *tempIdentity = NULL;
        tempIdentity = CFDictionaryGetValue(ident, kSecImportItemIdentity);
        *identity = (SecIdentityRef)tempIdentity;
    }
    
    if (options) {
        CFRelease(options);
    }
    
    //    NSLog(@">>>>>>>> inP12Data = %@", inP12Data);
    //    NSLog(@">>>>>>>> identity = %@", identity);
    
    return securityError;
}

 

之后想要获取数据,不用设置验证模式啊什么的,直接调用

- (void)testHttps {    manager = [AFHTTPSessionManager manager];        [manager GET:@"https://www.iyaoguang.com:8443/App/login?phone=123&password=123" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {        NSLog(@"???????????? %@",responseObject);    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {        NSLog(@"?????????? %@",error);    }];}

 

 

成功!

 

转载于:https://www.cnblogs.com/weak/p/6142508.html

你可能感兴趣的文章
在mui中创建aJax来请求数据..并展示在页面上
查看>>
spring 之AOP
查看>>
总结 15/4/23
查看>>
Windows 7环境下网站性能测试小工具 Apache Bench 和 Webbench使用和下载
查看>>
C#常见错误解决方法
查看>>
安装cnpm (npm淘宝镜像)
查看>>
Java 面向对象(基础) 知识点总结I
查看>>
读书笔记《自控力》
查看>>
区域生长算法
查看>>
hive学习2(Navicat连接hive)
查看>>
getResourceAsStream的3种路径配置
查看>>
switch语句小练习
查看>>
组合逻辑电路
查看>>
POP-一个点击带有放大还原的动画效果
查看>>
UE4材质是什么样的机制
查看>>
使用QTP录制自带Flight小实例
查看>>
Loadrunner脚本编程(4)-数据类型操作和字符串操作
查看>>
STL 算法
查看>>
分享:Backbone.js 样例站点与入门指南
查看>>
图的基本算法
查看>>