IOS 安全网络请求--HTTPS

如今在移动APP开发领域,网络安全问题已经提到日程。在iOS9中,苹果引入了HTTPS请求。我分析没有那么的全面生动,我只是把我自己在做这个过程中遇到坎分享出来,我自己在以后的过程也可以及时的复习一下。写的不好,请多多包涵!

 一.HTTPS

其实HTTPS从最终的数据解析的角度,与http没有任何区别,HTTPS就是将http协议数据包放到ssl/tsl层加密后,在tcp/ip层组成的IP数据报去传输,以此保证传输数据的安全;好吧,我实在是说不下去了,关于一些概念的东西,自己百度吧(太多了)。我放一张HTTPS请求的说明图给大家看一下,:HTTPS协议图

大概流程:
1. 客户端向服务器端发起连接请求,上送信息有:支持协议版本、随机数 1、加密方法、支持压缩算法;
2.服务器回应,下发信息有:确认协议版本、随机数2、确认加密方法、服务器公钥证书;
3.客户端再次上送信息:随机数3(采用公钥加密)、编码改变通知、客户端握手结束通知;
4.服务器采用随机数1、随机数2和随机数3组成会话密钥,并回应:编码改变通知、服务器握手结束通知。
以上四次握手中,完成了几件事情,第一,证书下发;第二,会话密钥;第三,确认双方参数(双方协议版本、加密方法等)。其中随机数1和随机数2是明文,随机数3是密文,之所以采用三个随机数来确定会话密钥,主要是三组随机数组成的随机数,确保了随机数的随机性,从而保证每次生成的会话密钥的安全性。

二.基础的知识了解过后,我们来一些干货。
1.创建证书
正常情况下,服务端的开发人员会有明文的证书(.pem)。我们需要把这个证书改成Xcode可以使用的证书。具体做法是通过钥匙串程序打开来,然后导出到桌面保存为.cer的文件。
2.下面就是具体代码编写
上代码前,先来了解一下系统的API的验证流程:

A: 获取需要验证的信任对象(Trust Object),在NSURLConnection来说,是从delegate方法-connection:willSendRequestForAuthenticationChallenge:回调回来的参数challenge中获取([challenge.protectionSpace serverTrust]);
B:采用系统默认方式验证Trust Object,SecTrustEvaluate会根据Trust Object的验证策略,一级一级往上,验证证书上每一级数字签名的有效性,从而评估证书的有效性;
C:通过上一步,一般安全要求下,直接验证通过,下一步使用Trust Object生成一份凭证([NSURLCredential credentialForTrust:serverTrust]),传入challenge的sender中([challenge.sender useCredential:cred forAuthenticationChallenge:challenge])处理,建立连接;
D:如果有更强的安全要求,还可以继续对Trust Object进行更严格验证,常用方式为在本地导入证书,验证Trust Object与导入证书是否匹配;
E:如果验证失败,取消此次Challenge-Response Authentication验证流程,拒绝连接请求。如果是自建证书,那么会跳过第二步,因为自建证书的根CA数字签名不在系统的信任列表中。
上代码

1.导入证书:
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"miniclouds" ofType:@"cer"];
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
SecCertificateRef certifucate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(certData));
//self.trustedCertificates 就是普通的 NSArray
self.trustedCertificates = @[CFBridgingRelease(certifucate)];

`
2.发送请求

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://miniclouds.cn:8080/faces/recognition/livingrecognize"]];
        request.HTTPMethod = @"POST";
        NSDictionary *jsonData = @{@"session_info":@{
                                           @"user":@"testBD",
                                           @"password":@"123456"
                                           }
                                   };
        NSData *data = [NSJSONSerialization dataWithJSONObject:jsonData options:NSJSONWritingPrettyPrinted error:nil];
        request.HTTPBody = data;
        NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
        [connection start];

3.代理回调

//1 代理回调 NSURLConnectionDelegate
-(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{

    NSLog(@"333:will send Request!!");
    //1.获取trust对象
    SecTrustRef trust = challenge.protectionSpace.serverTrust;
    SecTrustResultType result;
    //注意:这里将之前导入的证书设置成下面验证的Trust Object的anchor certificate
    SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)self.trustedCertificates);

    //2.SecTrustEvaluate会查找前面SecTrustSetAnchorCertificates设置的证书或者系统默认提供的证书,对trust进行验证
    OSStatus status = SecTrustEvaluate(trust, &result);
    if (status == errSecSuccess && (result == kSecTrustResultProceed || result == kSecTrustResultUnspecified)) {

        //3.验证成功,生成NSURLCredential凭证cred,告知challenge的sender使用这个凭证来继续连接
        NSURLCredential *credential = [NSURLCredential credentialForTrust:trust];
        [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
    }else{

        //4.验证失败,取消这次验证流程
        [challenge.sender cancelAuthenticationChallenge:challenge];
    }

}

//2 代理回调 NSURLConnectionDataDelegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
   NSLog(@"444:didReceiveResponse");
    self.receiveData = [[NSMutableData alloc] init];
}


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    NSLog(@"555:didReceiveData");
    [self.receiveData appendData:data];

}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    NSLog(@"666:didFailWithError");

    NSLog(@"error%@",error.description);
}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection{

    NSLog(@"777:connectionDidFinishLoading");

    NSString *returnString = [[NSString alloc] initWithData:self.receiveData encoding:NSUTF8StringEncoding];

    NSLog(@"returnString:%@",returnString);


}

三.总结
我在做AFNetworking的时候老是报错,所以就没有写在上面。以后有机会再往上面补,如果有好的建议可以私信我。
四.参考文章
1.ios https
2.SSL/TLS协议运行机制的概述
3.图解SSL/TLS
4.iOS访问https ssl和tls双向加密

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值