天天看点

【Https】iOS端两种Https数据传输加密方法

http数据传输传输的是明文,未进行加密的数据链可以在网络中设置代理进行截取,尽管会有token等验证手段,但数据被监听还是不可避免的,这点使用网络抓包软件就能做到。

而对于https数据加密后传输的数据,抓到的数据包都只是乱码,安全性大幅提高,也是当前大势所趋。

下面是使用ASIHttpRequest 和 AFNetworking两种三方库进行https加密的方式的代码整理。

原料:

1、相应的ASIHttpRequest、AFNetworking配置完成

2、相应的证书文件

一、ASIHttpRequest

参考【Ranger-Lee】《ASIHTTPRequest 使用HTTPS》

/*
 测试https接口
 */
 + (void)testClientCertificate {
    NSURL *httpsUrl = [NSURL URLWithString:@"https://www.demo.com/method.php"];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:httpsUrl];    
    SecIdentityRef identity = NULL;
    SecTrustRef trust = NULL;
    NSData *cerData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"证书文件名" ofType:@"文件类型"]];
    [[self class] extractIdentity:&identity andTrust:&trust fromPKCS12Data:cerData];
    request = [ASIHTTPRequest requestWithURL:httpsUrl];
    [request setClientCertificateIdentity:identity];
    /*
    是否验证服务器端证书必须为合法证书
    */
    [request setValidatesSecureCertificate:NO];
    [request setRequestMethod:@"GET"];
    [request startSynchronous];
    NSError *error = [request error];
    if (!error) {
        NSString *response = [request responseString];
        NSLog(@"response is : %@",response);
        NSLog(@"获取数据成功");
    } else {
        NSLog(@"Failed to save to data store: %@", [error localizedDescription]);
        NSLog(@"%@",[error userInfo]);
    }
}


/*
 提取证书
 */
+ (BOOL)extractIdentity:(SecIdentityRef *)identityRef andTrust:(SecTrustRef*)trustRef fromPKCS12Data:(NSData *)CerData
{
    OSStatus securityError = errSecSuccess;
    
    NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:@"证书密码" forKey:(id)kSecImportExportPassphrase];
    
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    securityError = SecPKCS12Import((CFDataRef)CerData,(CFDictionaryRef)optionsDictionary,&items);
    
    if (securityError == 0) {
        CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
        const void *tempIdentity = NULL;
        tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
        *identityRef = (SecIdentityRef)tempIdentity;
        const void *tempTrust = NULL;
        tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
        *trustRef = (SecTrustRef)tempTrust;
    } 
           
else 
           
{
        NSLog(@"Failed with error code %d",(int)securityError);
        /*
        若报错 -26275  文件读取不出数据,此时可将文件格式进行更改,再重新导入项目,<span style="font-family: Arial, Helvetica, sans-serif;">测试时使用pfx证书测试通过
</span>        */
        return NO;
    }
    return YES;
}
           

二、AFNetworking

参考 【七七】《iOS 开发笔记-AFNetWorking https SSL认证》

/*
 测试https接口
 */
+ (void)testClientCertificate
{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    
    /*
     Https SSL 验证。
     */
    [manager setSecurityPolicy:[self SetSecurityPolicy]];
    
    [manager GET:@"https://www.demo.com/method.php" parameters:nil progress:^(NSProgress * _Nonnull downloadProgress)
     {
         NSLog(@"%@",downloadProgress);
     }
         success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
             NSData * responsedata=(NSData *)responseObject;
             NSString * response =[[NSString alloc]initWithData: responsedata encoding:NSUTF8StringEncoding];
             NSLog(@"%@", response);
             NSLog(@"获取数据成功");
         }
         failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull   error) {
             NSLog(@"%@",error);
         }];
}


/*
 设置安全证书
 */
+ (AFSecurityPolicy * )SetSecurityPolicy
{
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"证书名称" ofType:@"证书后缀"];
    NSData *certData = [NSData dataWithContentsOfFile:cerPath];
    /*
    AFSSLPinningModeCertificate 使用证书验证模式
     */
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];

    /*
     allowInvalidCertificates 是否允许自建证书,默认为NO
     */
    securityPolicy.allowInvalidCertificates = NO;

    /*
     validatesDomainName 是否需要验证域名,默认为YES;
     */
    securityPolicy.validatesDomainName = YES;
    securityPolicy.pinnedCertificates = [NSSet setWithArray:@[certData]];
    return securityPolicy;
}