发表日期:2016-12 文章编辑:小灯 浏览次数:2631
由于苹果规定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要求, 有以下两种方法:
腾讯云提供的检测页面检测
终端输入 nsurl --ats-diagnostics --verbose 你的接口地址
大家可以参考这篇文章,里面的说的很明白:
关于iOS9中的App Transport Security相关说明及适配(更新于2016.7.1)
里面会详细说明你的证书哪点不符合ATS要求
当然下面自己制作证书去实现HTTPS的,检测不通过的,所以我觉得审核会被拒
这种方法配置好了, 在手机端就什么都不用配置就可以请求了
苹果官方信任证书里说到有三种证书:
很明显没有绿锁, 当打开的时候会询问是否连接这个不受信任的连接才会进一步打开, 下面就来一步步的实现(包括怎么制作证书)
iOS使用自签名证书实现HTTPS请求
iOS Https协议 自签证书访问数据参考这个例子的时候,博主自带的Demo AFN框架请求不了数据, 我用了最新AFN版本的成功返回数据
还可以参考一下
iOS 10 适配 ATS app支持https通过App Store审核
我在利用原生的代码测试时遇到的问题
@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 *)responsecompletionHandler:(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 *)challengecompletionHandler:(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: credentialforAuthenticationChallenge: 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.利用系统的方法来不到
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challengecompletionHandler:(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];
希望帮到你。
日期:2018-04 浏览次数:6759
日期:2017-02 浏览次数:3434
日期:2017-09 浏览次数:3652
日期:2017-12 浏览次数:3524
日期:2018-12 浏览次数:4813
日期:2016-12 浏览次数:4579
日期:2017-07 浏览次数:13641
日期:2017-12 浏览次数:3504
日期:2018-06 浏览次数:4263
日期:2018-05 浏览次数:4442
日期:2017-12 浏览次数:3554
日期:2017-06 浏览次数:3978
日期:2018-01 浏览次数:3939
日期:2016-12 浏览次数:3906
日期:2018-08 浏览次数:4422
日期:2017-12 浏览次数:3702
日期:2016-09 浏览次数:6402
日期:2018-07 浏览次数:3204
日期:2016-12 浏览次数:3226
日期:2018-10 浏览次数:3376
日期:2018-10 浏览次数:3476
日期:2018-09 浏览次数:3574
日期:2018-02 浏览次数:3593
日期:2015-05 浏览次数:3516
日期:2018-09 浏览次数:3302
日期:2018-06 浏览次数:3432
日期:2017-02 浏览次数:3867
日期:2018-02 浏览次数:4333
日期:2018-02 浏览次数:4169
日期:2016-12 浏览次数:3570
Copyright ? 2013-2018 Tadeng NetWork Technology Co., LTD. All Rights Reserved.