iOS 原生库对 https 的处理
来源:互联网 发布:二次元衣服淘宝店 编辑:程序博客网 时间:2024/05/21 15:49
转载自:swift cafe
使用 NSURLSession
NSURLSession 是 iOS 原生提供的网络处理库。它提供了丰富的接口以及配置选项,满足我们平时网络处理的大部分需求,同时它也支持 https。关于 NSURLSession 的基本内容,可以参看之前的这篇文章:
NSURLSession 网络库
这次我们主要介绍使用 NSURLSession 对 https 的处理,关于 https 的基本原理,大家可以参看这里:
Https 与 iOS 信息安全
好了,准备知识都了解了之后,我们就可以开始了。
NSURLSession 默认是支持 https 处理的, 包括证书验证, https 握手等操作, 都已经帮我们处理过了, 举个例子:
if let url = NSURL(string: "https://httpbin.org/get") { NSURLSession.sharedSession().dataTaskWithURL(url) { data, response, error in print("%@",NSString(data: data!, encoding: NSUTF8StringEncoding)) //成功输出 }.resume()}
这里我们用 https 协议访问了一个地址。 就像访问普通的 http 地址一样, NSURLSession 的回调中成功的输出了返回的数据,我们完全没有进行任何的额外处理,就已经可以访问 https 地址了。
是的,这种情况对于服务器的证书正确的情况下,是没问题的。因为 NSURLSession 的内部处理机制中已经预置了可信任的根证书的。只要你访问的地址使用的 SSL证书,是用这些跟证书机构授权的,就不会有问题。
但还存在这样一种情况,就是如果你访问的地址所使用的证书,不是这些颁发机构授权的, 而是它们自己生成的(这也叫自签名证书), 问题就出现了。比如我们再用同样的 API 访问另一个地址:
if let url = NSURL(string: "https://www.pcwebshop.co.uk") { NSURLSession.sharedSession().dataTaskWithURL(url) { data, response, error in //... }.resume()}
如果执行这段代码的话,你会在控制台中收到这样一个错误:
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
很明显,SSL 证书验证失败了,并且这个时候 dataTaskWithURL 方法的回调闭包中,不会返回任何数据。 所以我们在设计客户端使用 https 协议进行交互的时候,虽然大部分逻辑 iOS 原生库都已经帮我们处理好了,但这种证书验证失败的情况还是需要大家注意一下的。
其实 iOS 默认的这种实现也是有一定道理的,证书验证失败的站点,从原则上来说是不可信,不安全的。 所以原生库在默认情况下拒绝这样的链接也是正确的。
自定义证书验证行为我们平常使用的大多数浏览器也是有这样的逻辑的,如果发现证书验证失败,就会给用户提示一个警告,让用户选择是否要继续访问。 iOS 原生库的通用原则是拒绝一切未经验证的证书, 这种行为可以很好的保证用户的安全。
但是,我们有一些自己特定的需求怎么办呢, 比如我们自己的 app 接口使用的是 https 方位我们自己的服务器, 但我们自己的服务器使用的是自签名证书, 如果按照默认行为的话, 尽管我们自己确信这个自签名证书是安全的,接口的访问也永远不会成功。 因为它不在 iOS 原生库的信任列表中。
这时候,我们就需要更深入的处理证书验证的细节了, NSURLSession 也给我们提供了相应的 API。 要在这些 API 中加入我们自己的验证逻辑,我们需要实现 NSURLSessionDelegate 的 didReceiveChallenge 方法:
func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) { if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { let credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!) completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, credential) }}
didReceiveChallenge 方法中,首先通过 authenticationMethod 属性检测服务端的验证方式, 只有是 NSURLAuthenticationMethodServerTrust 的时候我们才进行处理。 NSURLAuthenticationMethodServerTrust 代表的就是 https 验证。
再看一下 if 分支里面的处理, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
这里创建了一个授信,告诉系统服务器返回的这个证书是可信的。这样这个自签名的证书也能获得通过了。
再次运行程序,就可以看到这个自签名的地址能够正常访问了。
如果你是 iOS 9 以上的系统,还要记得修改一下 Info.plist 里面的 App Transport Security Settings 设置,在里面加上这一段即可:
<key>NSAppTransportSecurity</key><dict> <key>NSAllowsArbitraryLoads</key> <true/></dict>
否则,这种请求也会被 iOS 的全局设置阻拦的。
- iOS 原生库对 https 的处理
- iOS对https的支持
- iOS-71-关于iOS、Android、服务端对键盘原生表情的处理
- HIBERNATE对原生SQL的处理
- iOS原生二维码处理
- ios 配置https对证书的要求
- iOS上实现对HTTPS的支持
- iOS对HTTPS支持
- 对原生js事件对象处理的封装
- IOS对dealloc的处理
- IOS 对XML的处理
- ios 对图片的处理
- Windows与linux下,curl对HTTPS协议的处理
- 如何在iOS上实现对HTTPS的支持
- 如何在iOS上实现对HTTPS的支持
- iOS 中对 HTTPS 证书链的验证
- iOS 中对 HTTPS 证书链的验证
- 原生类型的处理
- Python基础学习(七)
- 解决 无法读取到 /data/data/yourPackageName/files/coverage.ec 文件
- 爬虫钛媒体科技新闻
- 自加自减运算符的错误使用和理解【个人学习笔记,如有错误欢迎指正】
- Robotframework(4):创建变量的类型和使用
- iOS 原生库对 https 的处理
- Redis集群:基于twemproxy的实现
- 项目中使用aar
- glide加载到自定义圆形imageview不显示的问题
- JDK1.8新特性
- Spark 调研报告
- HashMap 与 ConcurrentHashMap 的区别
- 第十五章 套接字和标准I/O
- Codeforces AIM Tech Round 4 (Div. 2) A. Diversity