文档章节

iOS 如何升级到https

卡奇匠
 卡奇匠
发布于 2016/12/13 14:36
字数 1941
阅读 115
收藏 0

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

 

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

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

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

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

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

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

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 可信的根证书用于建立信任链,以验证由可信的根签署的其他证书,例如,与 Web 服务器建立安全连接。当 IT 管理员创建 iPhone、iPad 或 iPod touch 的配置描述文件时,无需提供这些可信的根证书。

2 始终询问的证书不受信任,但不受阻止。使用其中一个证书时,系统将提示您选择是否信任该证书。

3 已阻止的证书视为被盗用,将不再受信任。

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

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

自己制作证书

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

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

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

还可以参考一下 

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

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

@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的图片时,大家可以绕过证书验证去加载图片 

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

希望帮到你。 

© 著作权归作者所有

共有 人打赏支持
卡奇匠
粉丝 23
博文 67
码字总数 68740
作品 0
海淀
程序员
私信 提问
苹果iOS的八年:如何一步步爬到了这么高

电脑需要操作系统,手机也需要,2007 年,苹果带着旗下第一款智能手机 iPhone 和第一款操作系统亮相,从而奠定了改变世界的基础。8 年时间以来,iPhone 一直在不停的进化、演变,iOS 操作系统...

oschina
2015/09/08
4K
22
【AR】开始使用Vuforia开发iOS(2)

原 设置iOS开发环境 安装Vuforia iOS SDK 如何安装Vuforia iOS示例 编译并运行Vuforia iOS示例 支持iOS金属 iOS 64位迁移 设置iOS开发环境 适用于iOS的Vuforia引擎目前支持运行iOS 9及更高版...

lichong951
2018/06/11
0
0
iOS 9.3.4 发布:这是一次重要的安全性更新

苹果今天发布了 iOS 9.3.4 升级补丁,距离 iOS 9.3.3 发布相隔两周的时间。目前,iOS 10 正在测试之中,还有不到两个月的时间就会有正式版。iOS 9.3.4 可以通过 OTA 无线升级。 根据苹果的发...

oschina
2016/08/05
3.4K
14
苹果紧急发布 iOS 8.0.2,修复 iPhone 6 升级问题

苹果刚刚发布了 iOS 8.0.2, 意在修复 iOS 8.0.1 中带来的无运营商信号, Touch ID 不好用等故障, 还包括 iOS 8.0.1 中带来的其他修补. 用户现在已经可以通过 OTA 升级. iPhone 6/6 Plus 的用户...

神州浪子
2014/09/26
2.7K
23
iOS 8 普及率达到 82%,Android 5.0 只有 1.6%

根据苹果为开发者提供的 App Store 支持页面,公司最新的移动操作系统,iOS 8 ,目前已经被72%的 iOS 设备安装。iOS 8 在2014年9月发布,至今过去了5个月。 安装普及率比去年12月中旬增加了9...

oschina
2015/02/04
3.8K
45

没有更多内容

加载失败,请刷新页面

加载更多

[walminer bug分析]checkpoint wal记录的lsn与checkpoint记录的redo点的关系

问题背景 walminer工具的用户反馈来一个问题,不管添加了多少wal日志,想要的wal文件的解析结果总是有未解析出的部分。 分析问题 分析问题发现,checkpoint wal记录之后对某个数据page进行修...

movead
48分钟前
4
0
OSChina 周二乱弹 —— 金 冈刂 犭良

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @蓝瞳 :分享骇物乐团的单曲《I'll be the one》: 《I'll be the one》- 骇物乐团 手机党少年们想听歌,请使劲儿戳(这里) @尾生 :工作使人...

小小编辑
54分钟前
370
10
python中类方法和静态方法区别

面相对象程序设计中,类方法和静态方法是经常用到的两个术语。 逻辑上讲:类方法是只能由类名调用;静态方法可以由类名或对象名进行调用。 在C++中,静态方法与类方法逻辑上是等价的,只有一...

xiangyunyan
今天
14
0
Hibernate SQLite方言

以下代码有参考过github上国外某位大佬的,在发文的最新稳定版Hibernate上是可用的,有时间再仔细分析一下 import org.hibernate.dialect.Dialect;import org.hibernate.dialect.function.S...

CHONGCHEN
今天
4
0
CentOS 7 MariaDB搭建主从服务器

本文编写环境为CentOS7。确保关闭SELinux,关闭防火墙或者防打开指定端口。具体信息如下 #master[root@promote ~]# cat /etc/redhat-release CentOS Linux release 7.6.1810 (Core) [r...

白豆腐徐长卿
今天
14
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部