【Objective-c】 使用自签证书实现HTTPS

2016年苹果在发布会上信誓旦旦的宣布2017年1月1日全面实现https,所有已经上架或提交审核的都必须更换,否则审核不通过,下架。因此对https做了一些了解。

1、https原理
Paste_Image.png

HTTPS 是 http 的升级版,使信息的交互更加安全。
HTTPS 是由 HTTP + SSL / TLS组成的。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。
具体的加密和解密如下:

  1. 客户端发起HTTPS请求
    这个没什么好说的,就是用户在浏览器里输入一个https网址,然后连接到server的443端口。(http 连接的是server的80端口)
  2. 服务端的配置
    采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面(startssl就是个不错的选择,有1年的免费服务)。这套证书其实就是一对公钥和私钥。如果对公钥和私钥不太理解,可以想象成一把钥匙和一个锁头,只是全世界只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。
  3. 传送证书
    这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。
  4. 客户端解析证书
    这部分工作是有客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随即值。然后用证书对该随机值进行加密。就好像上面说的,把随机值用锁头锁起来,这样除非有钥匙,不然看不到被锁住的内容。
  5. 传送加密信息
    这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。
  6. 服务段解密信息
    服务端用私钥解密后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进行对称加密。所谓对称加密就是,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,所以只要加密算法够彪悍,私钥够复杂,数据就够安全。
  7. 传输加密后的信息
    这部分信息是服务段用私钥加密后的信息,可以在客户端被还原
  8. 客户端解密信息
    客户端用之前生成的私钥解密服务段传过来的信息,于是获取了解密后的内容。整个过程第三方即使监听到了数据,也束手无策。
2、获取证书
Paste_Image.png

上图是双向认证的示意图:客户端Client 和 服务端Server 都有一个证书信任库,因为是自签的,所以需要将证书导入,这样才能验证证书是否合法。比如:客户端要验证服务端的证书是否有效,就必须导入服务器的证书,做对比,获取服务器的证书方法如下:
使用IE浏览器,打开连接


D(0WAMWU`L8NUK9O)A7$B1.png
ORA6D_G@36UG44HCHU5{XZM.png
%$R3Z$})%$OQ3WAUPOY0}FC.png
80SJKL3(0S6~ZH`}HHX$161.png
UEEBFITOL0KZ2~W87%29UGP.png

![]SHQY$BWN{__8U@P((ZRQ.png](http://upload-images.jianshu.io/upload_images/1923392-00dbf4b2017e5dd0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

到此为止,证书获取成功

3、代码配置

本人用的是AFNetworking第三框架,配置如下。在请求方法中添加以下代码

    //https         
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
    securityPolicy.allowInvalidCertificates = YES;  //是否允许使用自签证书
    securityPolicy.validatesDomainName = NO;        //是否需要验证域名,默认是YES
    
    NSString *requestString = [NSString stringWithFormat:@"%@%@",URLDoman,methodName];
    _session = [AFHTTPSessionManager manager];
    _session.responseSerializer = [AFHTTPResponseSerializer serializer];
    _session.securityPolicy = securityPolicy;    //设置证书校验模式
    
    //设置超时
    [_session.requestSerializer willChangeValueForKey:@"timeoutinterval"];
    _session.requestSerializer.timeoutInterval = TimeoutInterval;
    [_session.requestSerializer didChangeValueForKey:@"timeoutinterval"];
    _session.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringCacheData;
    
    //身份验证回调
    __weak typeof(self) weakSelf = self;
    [_session setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession * _Nonnull session, NSURLAuthenticationChallenge * _Nonnull challenge, NSURLCredential *__autoreleasing  _Nullable * _Nullable credential) {
        //获取服务器的trust object
        SecTrustRef serverTrust = [[challenge protectionSpace]serverTrust];
        //导入多张CA证书
        NSString *cerPath = [[NSBundle mainBundle]pathForResource:@"ca" ofType:@"cer"];//自签证书
        NSData *caCert = [NSData dataWithContentsOfFile:cerPath];
        NSArray *cerArray = @[caCert];
        weakSelf.session.securityPolicy.pinnedCertificates = cerArray;
        
        SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert);
        NSCAssert(caRef!=nil, @"caRef is nil");
        
        NSArray *caArray = @[(__bridge id)(caRef)];
        NSCAssert(caArray != nil, @"caArray is nil");
        
        OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
        SecTrustSetAnchorCertificatesOnly(serverTrust, NO);
        NSCAssert(errSecSuccess == status, @"SecTrustSetAnchorCertificates failed");
        
        //选择质询认证的处理方式
        NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
        __autoreleasing NSURLCredential *credentiall = nil;
        
        //NSURLAuthenticationMethodServerTrus咨询认证方式
        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
            //基于客户端的安全策略来决定是否信任该服务器,不信任则响应质询
            if ([weakSelf.session.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
                //创建质询证书
                credentiall = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                //确认质询方式
                if (credential) {
                    disposition = NSURLSessionAuthChallengeUseCredential;
                }else{
                    disposition = NSURLSessionAuthChallengePerformDefaultHandling;
                }
            }else{
                //取消质询
                disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
            }
        }else{
            disposition = NSURLSessionAuthChallengePerformDefaultHandling;
        }
        
        return disposition;
    }];

注意项:
苹果ATS对HTTPS证书也是有要求的
a、服务器所有的连接使用TLS1.2以上版本
b、HTTPS证书必须使用SHA256以上哈希算法签名
c、HTTPS证书必须使用RSA 2048位或ECC 256位以上公钥算法
d、使用前向加密技术

到此,启动App网络请求是没什么问题的了。

提醒:使用自签的证书,苹果审核不一定能通过。祝大家好运....

好文推荐:(码文的搬运工)
HTTPS原理
双向认证
单双向认证
iOS用自签名证书实现HTTPS请求的原理实例讲解

iOS开发HTTPS实现之信任SSL证书和自签名证书
iOS使用自签名证书实现HTTPS请求


20170216 补充
单向认证和双向认证的使用场景:
单向认证:一般都是使用在Web页面,用于提示用户当前访问页面没有得到验证,访问有风险。但是依然能够访问
双向认证:移动端建议是使用双向认证,安全性强,并且如果是只使用单向认证的话,跟http无区别,得不到安全保障。有如下两种情况出现:
第一:如果移动端使用https请求https服务端,移动端就会验证服务端的证书有效性,如果不是新人的证书,则禁止访问。
第二:如果移动端使用https请求http服务端,因为http是超文本,是无状态协议的,所以只要访问的资源存在就会返回数据给移动端。这样的话,就失去了验证服务器合法的作用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容