由于苹果规定2017年1月1日以后,所有APP都要使用HTTPS进行网络请求,否则无法上架,因此研究了一下在iOS中使用HTTPS请求的实现。网上搜索了一些比较有用资料,大家可以参考下

苹果强制升级的HTTPS不仅仅是在接口HTTP上加个S那么简单:

它所有满足的是iOS9中新增App Transport Security(简称ATS)特性:

那满足ATS我们需要做什么呢

1.必须是苹果信任的CA证书机构颁发的证书

2.后台传输协议必须满足: TLS1.2 (这很重要, 后面的自制证书满足这个条件是前提)

3.签字算法只能是下面的一种:

1
2
3
4
5
6
7
8
9
10
11
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

4.证书必须使用SHA256或者更好的哈希算法进行签名,要么是2048位或者更长的RSA密钥,要么就是256位或更长的ECC密钥。

目前有两种升级到HTTPS得方法:

1.第三方认证的颁发CA证书(推荐)

2.自己制作证书(这种不知道能不能满足苹果的审核)

一: 第三方认证的颁发CA证书

证书到底长什么样子呢? 取个栗子:

大家请打开https://www.baidu.com

然后看到

百度的证书分析

那些证书机构颁发的证书能用:苹果官方信任证书

收费SSL证书: 网上百度一大把, 收费还挺贵的,自己可以多找几个对比一下

免费SSL证书: 除了收费的CA证书机构, 你还可以去腾讯云申请免费的SSL证书, 教程免费在腾讯云申请SSL证书的方法

沃通(WoSign)免费的SSL证书最近被苹果封杀了, 能不能用大家可以看一下苹果的公告: 您的苹果手机轻点“设置”>“通用”>“关于本机”>"证书信任设置">"进一步了解被信任的证书"去了解

检测你的接口是否满足苹果的ATS要求, 有以下两种方法:

  1. 腾讯云提供的检测页面检测

腾讯云的检测页面

2 终端输入 nsurl --ats-diagnostics --verbose 你的接口地址

大家可以参考这篇文章,里面的说的很明白:

关于iOS9中的App Transport Security相关说明及适配(更新于2016.7.1)

里面会详细说明你的证书哪点不符合ATS要求

当然下面自己制作证书去实现HTTPS的,检测不通过的,所以我觉得审核会被拒

这种方法配置好了, 在手机端就什么都不用配置就可以请求了

二: 自己制作证书

苹果官方信任证书里说到有三种证书:

1
2
3
1 可信的根证书用于建立信任链,以验证由可信的根签署的其他证书,例如,与 Web 服务器建立安全连接。当 IT 管理员创建 iPhone、iPad 或 iPod touch 的配置描述文件时,无需提供这些可信的根证书。
2 始终询问的证书不受信任,但不受阻止。使用其中一个证书时,系统将提示您选择是否信任该证书。
3 已阻止的证书视为被盗用,将不再受信任。

自制证书我觉得应该就是属于第二种情况, 所以这种方法我也不知道能不能通过苹果的审核, 只是提供一个方法给大家参考, 看到网上有人说可以,有人说不可以, 不到1月1号,自己没试过都不敢说大话

这种方式拿到后台的接口用谷歌浏览器打开跟百度的证书是有区别的

自己制作证书

很明显没有绿锁, 当打开的时候会询问是否连接这个不受信任的连接才会进一步打开, 下面就来一步步的实现(包括怎么制作证书)

iOS使用自签名证书实现HTTPS请求

iOS Https协议 自签证书访问数据参考这个例子的时候,博主自带的Demo AFN框架请求不了数据, 我用了最新AFN版本的成功返回数据

还可以参考一下

iOS 10 适配 ATS app支持https通过App Store审核

我在利用原生的代码测试时遇到的问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
@interface ViewController () @end
@implementation ViewController
- (void)viewDidLoad {
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
   NSURLSessionDataTask *task =  [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }];
   [task resume];
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
    NSLog(@"接收到服务器响应");
    //注意:这里需要使用completionHandler回调告诉系统应该如何处理服务器返回的数据
    //默认是取消
    /**
     NSURLSessionResponseCancel = 0,            默认的处理方式,取消
     NSURLSessionResponseAllow = 1,             接收服务器返回的数据
     NSURLSessionResponseBecomeDownload = 2,    变成一个下载请求
     NSURLSessionResponseBecomeStream           变成一个流
     */
    completionHandler(NSURLSessionResponseAllow);
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
    didReceiveData:(NSData *)data {
    NSLog(@"获取到服务段数据");
    NSLog(@"%@",[self jsonToDictionary:data]);
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(nullable NSError *)error {
    NSLog(@"请求完成%@", error);
}
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    NSLog(@"证书认证");
    if ([[[challenge protectionSpace] authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust]) {
        do
        {
            SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
            NSCAssert(serverTrust != nil, @"serverTrust is nil");
            if(nil == serverTrust)
                break/* failed */
            /**
             *  导入多张CA证书(Certification Authority,支持SSL证书以及自签名的CA),请替换掉你的证书名称
             */
            NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"ca" ofType:@"cer"];//自签名证书
            NSData* caCert = [NSData dataWithContentsOfFile:cerPath];
            NSCAssert(caCert != nil, @"caCert is nil");
            if(nil == caCert)
                break/* failed */
            SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert);
            NSCAssert(caRef != nil, @"caRef is nil");
            if(nil == caRef)
                break/* failed */
            //可以添加多张证书
            NSArray *caArray = @[(__bridge id)(caRef)];
            NSCAssert(caArray != nil, @"caArray is nil");
            if(nil == caArray)
                break/* failed */
            //将读取的证书设置为服务端帧数的根证书
            OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
            NSCAssert(errSecSuccess == status, @"SecTrustSetAnchorCertificates failed");
            if(!(errSecSuccess == status))
                break/* failed */
            SecTrustResultType result = -1;
            //通过本地导入的证书来验证服务器的证书是否可信
            status = SecTrustEvaluate(serverTrust, &result);
            if(!(errSecSuccess == status))
                break/* failed */
            NSLog(@"stutas:%d",(int)status);
            NSLog(@"Result: %d", result);
            BOOL allowConnect = (result == kSecTrustResultUnspecified) || (result == kSecTrustResultProceed);
            if (allowConnect) {
                NSLog(@"success");
            }else {
                NSLog(@"error");
            }
            /* kSecTrustResultUnspecified and kSecTrustResultProceed are success */
            if(! allowConnect)
            {
                break/* failed */
            }
#if 0
            /* Treat kSecTrustResultConfirm and kSecTrustResultRecoverableTrustFailure as success */
            /*   since the user will likely tap-through to see the dancing bunnies */
            if(result == kSecTrustResultDeny || result == kSecTrustResultFatalTrustFailure || result == kSecTrustResultOtherError)
                break/* failed to trust cert (good in this case) */
#endif
            // The only good exit point
            NSLog(@"信任该证书");
            NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
            return [[challenge sender] useCredential: credential
                          forAuthenticationChallenge: challenge];
        }
        while(0);
    }
    // Bad dog
    NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
    completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,credential);
    return [[challenge sender] cancelAuthenticationChallenge: challenge];
}
- (NSDictionary *)jsonToDictionary:(NSData *)jsonData {
    NSError *jsonError;
    NSDictionary *resultDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableLeaves error:&jsonError];
    return resultDic;
}
@end

下面说说我在配置自己制作证书过程中遇到的问题:

1.转换证书: 把后台给你的.crt证书转化为.cer后缀

终端命令行openssl x509 -in 你的证书.crt -out 你的证书.cer -outform der

2.利用系统的方法来不到

1
2
3
4
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    NSLog(@"证书认证");
}

这个方法的时候, 是因为后台的传输协议还没升级到TLS1.2, 叫后台升级后就可以来到验证证书的这个方法了.

3.拖入证书读取不出证书数据

参考: https的证书错误,错误码-1012问题及解决方案

SDWebImage: 项目中大家用到AFN请求网络数据, 升级验证SSL证书的方案相信你看完上面的参考文章已经没问题了, 我给出的代码, 自定义网络请求也没问题了, 还有就是SDWebImage框架的请求HTTPS的图片时,大家可以绕过证书验证去加载图片

1
[imageView sd_setImageWithURL:[NSURL URLWithString:urlString] placeholderImage:self.placeholder options:SDWebImageAllowInvalidSSLCertificates];

恩, 这就是这几天升级HTTPS觉得有帮助的参考和总结.希望帮到你。

iOS 升级HTTPS通过ATS你所要知道的的更多相关文章

  1. iOS升级HTTPS通过ATS你所要知道的

    由于苹果规定2017年1月1日以后,所有APP都要使用HTTPS进行网络请求,否则无法上架,因此研究了一下在iOS中使用HTTPS请求的实现.网上搜索了一些比较有用资料,大家可以参考下 苹果强制升级的 ...

  2. 苹果强制使用HTTPS传输了怎么办?——关于HTTPS,APP开发者必须知道的事

    WeTest 导读 2017年1月1日起,苹果公司将强制使用HTTPS协议传输.本文通过对HTTPS基础原理和通信过程内容的讲解,介绍APP开发者在这个背景下的应对办法. 几周前,我们在<htt ...

  3. Node.js 模块化你所需要知道的事

    一.前言 我们知道,Node.js是基于CommonJS规范进行模块化管理的,模块化是面对复杂的业务场景不可或缺的工具,或许你经常使用它,但却从没有系统的了解过,所以今天我们来聊一聊Node.js模块 ...

  4. 【转】关于字符编码,你所需要知道的(ASCII,Unicode,Utf-8,GB2312…)

    转载地址:http://www.imkevinyang.com/2010/06/%E5%85%B3%E4%BA%8E%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81%EF%BC ...

  5. 关于字符编码,你所需要知道的(ASCII,Unicode,Utf-8,GB2312…)

    字符编码的问题看似很小,经常被技术人员忽视,但是很容易导致一些莫名其妙的问题.这里总结了一下字符编码的一些普及性的知识,希望对大家有所帮助. 还是得从ASCII码说起 说到字符编码,不得不说ASCII ...

  6. 开发者所需要知道的 iOS 10 SDK 新特性

    转自:https://onevcat.com/2016/06/ios-10-sdk/ 写的很好啊.哈哈哈 总览 距离 iPhone 横空出世已经过去了 9 个年头,iOS 的版本号也跨入了两位数.在我 ...

  7. iOS开发HTTPS实现之信任SSL证书和自签名证书

    iOS开发HTTPS实现之信任SSL证书和自签名证书 转自:http://www.jianshu.com/p/6b9c8bd5005a/comments/5539345 (收录一下供自己学习用的) 字 ...

  8. 网站HTTP升级HTTPS完全配置手册

    本文由葡萄城技术团队于博客园原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 今天,所有使用Google Chrome稳定版的用户迎来了v68正式 ...

  9. 网站 HTTP 升级 HTTPS 完全配置手册

    网站 HTTP 升级 HTTPS 完全配置手册 今天,所有使用Google Chrome稳定版的用户迎来了v68正式版首个版本的发布,详细版本号为v68.0.3440.75,上一个正式版v67.0.3 ...

随机推荐

  1. 浅谈浏览器http的缓存机制

    针对浏览器的http缓存的分析也算是老生常谈了,每隔一段时间就会冒出一篇不错的文章,其原理也是各大公司面试时几乎必考的问题. 之所以还写一篇这样的文章,是因为近期都在搞新技术,想“回归”下基础,也希望 ...

  2. 2000条你应知的WPF小姿势 基础篇<78-81 Dialog/Location/WPF设备无关性>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000ThingsYou Should Know About C# 和 2,00 ...

  3. SQL Server 服务器磁盘测试之SQLIO篇(一)

    数据库调优工作中,有一部分是需要排查IO问题的,例如IO的速度或者RAID级别无法响应高并发下的快速请求.最常见的就是查看磁盘每次读写的响应速度,通过性能计数器Avg.Disk sec/Read(Wr ...

  4. python装饰器

    今天看了装饰器的一些内容,感觉@修饰符还是挺抽象的. 装饰器就是在不用改变函数实现的情况下,附加的实现一些功能,比如打印日志信息等.需要主意的是装饰器本质是一个高阶函数,她可以返回一个函数. 装饰器需 ...

  5. Html5 直接插入排序

    直接插入排序算法(Straight Insertion Sort),是排序算法中简单的一种算法,基本思想如下: 将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表.即:先将序列的第 ...

  6. Enterprise Solution 进销存管理软件 C/S架构,支持64位系统 物流,资金流,信息流全面集成

          定位  Target Customers 中小型生产制造企业,批发零售类,贸易企业 主要模块 Modules 采购.销售.库存.财务账款四大模块,包含企业运作过程中销售.采购.库存各岗位需 ...

  7. PHP 面向对象编程和设计模式 (5/5) - PHP 命名空间的使用及名称解析规则

    PHP高级程序设计 学习笔记 2014.06.12 命名空间概述 PHP 在 5.3.0 以后的版本开始支持命名空间.什么是命名空间?从广义上来说,命名空间是一种封装事物的方法.在很多地方都可以见到这 ...

  8. Logstash时区、时间转换,message重组

    适用场景 获取日志本身时间 日志时间转Unix时间 重组message 示例日志: hellow@,@world@,@2011-11-01 18:46:43 logstash 配置文件: input{ ...

  9. 【NLP】揭秘马尔可夫模型神秘面纱系列文章(四)

    维特比算法解决隐马尔可夫模型解码问题(中文句法标注) 作者:白宁超 2016年7月12日14:08:28 摘要:最早接触马尔可夫模型的定义源于吴军先生<数学之美>一书,起初觉得深奥难懂且无 ...

  10. ASP.NET Core 中文文档 第二章 指南(4.5)使用 SQL Server LocalDB

    原文:Working with SQL Server LocalDB 作者:Rick Anderson 翻译: 魏美娟(初见) 校对: 孟帅洋(书缘).张硕(Apple).许登洋(Seay) Appl ...