IOS 安全网络请求--HTTPS

来源:互联网 发布:mac游戏排行榜 编辑:程序博客网 时间:2024/05/04 01:01

如今在移动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双向加密

0 0
原创粉丝点击