iOS配置HTTPS

https://github.com/ChenYilong/iOS9AdaptationTips

配置方法 :http://oncenote.com/2014/10/21/Security-1-HTTPS/

HTTPS服务器信任评估

https://developer.apple.com/library/content/technotes/tn2232/_index.html


 关于https的简介和说明我都是参考下面的文章:(谢谢文章作者)

1.http://my.oschina.net/vimfung/blog/494687

2.http://oncenote.com/2014/10/21/Security-1-HTTPS/

3.http://blog.csdn.net/dachao_me/article/details/48624685?ref=myread

最新消息:苹果关于接入https的截止时间被延期了,具体截止时间尚未定,苹果推迟https接入截止时间,小伙伴们!别太着急了!

https的说明我就不多说了,想要了解详细内容查看上面的链接,很多专业名词我也不是很明白,只后悔大学的时候关于网络工程等一些课程没有好好听吧!我写这篇文章主要是为了iOS工程中http转化为https的教程。


1.修改info.plist中不安全的http兼容配置

           目前绝大多数工作为了解决https的问题,直接在info.plist中添加配置使得系统的请求类NSURLSession(NSURLConnection)默认的请求方式从https转化为http,

注意:加了这个配置后,http和https都是兼容的,如果是https请求,会继续走https,是http请求会继续走http

配置如下:

这种方法只能说治标不治本,再说苹果公司也做出了规定2017年上架的app必须使用https不然可能无法通过审核,所以为了适配https的第一步就是删除这个配置,讲默认请求方式设置成https。删除后再次启动程序会发现请求全部失败,这个错误相信大家都很熟悉,没错就是因为服务器不支持https导致的。


2.使用系统的NSURLSession(NSURLConnection)或者第三方的请求框架(AFNetworking)实现https适配

      我项目中使用的是AFNetworking 3.1,所以我先利用AFNetworking做适配(其实AFNetworking的https适配还是利用NSURLSession(NSURLConnection)做的适配,只不过NSURLSession(NSURLConnection)适配有点麻烦,AFNetworking的适配更加简单),原本的manager初始化不变,只不过需要为manager的securityPolicy设置值(不好意思哦!不知道怎么样才能添加规范的代码,只能用截图来代替了)。


添加完成之后还是出现上面的问题:

检查后发现请求的路径不对,之前都是http,忘记改成https了(请求的路径一定要跟服务器开发人员确定好了),修改完成后还是报错,抓狂!!还是很奇葩的错误,请求被取消了,错误码-999,

找了很多资料才发现还需要站点证书,上面请求失败可能是因为ssl第一次握手的时候验证没通过,然后就直接被取消了。所以这时候就需要获取站点的证书,获取的方法有两种:

1.通过openssl命令获取,命令如下(以百度为例):

openssl s_client -connect www.baidu.com:443 /dev/null | openssl x509 -outform DER > https1.cer

这个命令的目的就是直接在你的终端打开的当前目录下面下载某一站点的证书,但是我怎么都获取不到下载的证书都是空的,而且终端还报错,找不到错误的原因,没办法只能用第二种办法了

2.直接在浏览器中打开项目的任意一个接口的完整路径,如果你服务器支持https的话会在链接的前面出现一个小锁的图标(我使用的是safair浏览器),点击小锁会出现提示点击显示证书就会出现站点证书的信息了(以百度为例),点击证书的图标到桌面上就可以把证书下载到桌面上了,这样就获取到站点证书了(这种方式不知道会不会存在啥问题,但是到目前为止我没遇到啥问题)

获取到证书后把证书放到项目的mainbundle中,并用代码获取

这时候再跑起来,接口都能获取到数据了,成功了,不过到这里大家不知道会不会存在疑问,证书这么容易获取到,那别人获取了怎么办?就算用抓包工具拦截了请求里面的内容都是加密的,但是别人可以利用证书向我们服务器发请求的,是不是也存在点问题呢?这个问题我到现在还不是很明白,有的资料说这样获取的证书是公钥,没有私钥的话也是白费力气。

3.由于iOS做https适配的时候对服务器是有要求的(一个符合 ATS 要求的 HTTPS),所以出了问题也不一定是客户端的问题

       其实上面成功了,但是还有很多概念不是很清楚,例如啥叫ATS(App Transport Security),它跟https有啥关系呢?

App Transport Security(简称ATS)特性, 主要使到原来请求的时候用到的HTTP,都转向TLS1.2协议进行传输。这也意味着所有的HTTP协议都强制使用了HTTPS协议进行传输,ATS是在iOS 9.0 和 OS X v10.11版本中增加的特性,使用iOS 9.0或者OS X v10.11的SDK版本(或更新的SDK)进行编译应用时会默认启动ATS。则需要对ATS进行配置。如果使用iOS 9.0或者OS X v10.11之前的SDK版本编译的应用默认是禁止ATS的,因此不会影响应用的网络连接方面的功能(即使在iOS 9.0的机子上跑也是不影响的)。其实ATS并不单单针对HTTP进行了限制,对HTTPS也有一定的要求:

首先颁发给服务器证书的证书机构(CA)的根证书必须是内置于操作系统(哪些根证书被信任可以查看https://support.apple.com/zh-cn/HT205205,或者在你的机子的设置-通用-关于本机最下面的“进一步了解被信任的证书”中查看,百度的CA根证书:)或者受用户或者系统管理员信任并安装到操作系统上的。而且必须要基于TLS 1.2版本协议(以百度为例,最好使用chrome浏览器,其他的浏览器我没找到查看TSL协议的版本号)。再来就是连接的加密方式要提供Forward Secrecy(FS正向保密,感兴趣的筒子可以看看这个https://vincent.bernat.im/en/blog/2011-ssl-perfect-forward-secrecy.html,--!已经打不开了,支持Forward Secrecy的加密方式

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

),文档中罗列出了支持的加密算法(上面的原文中有说明,我把它独立抽出来放到下面表格中查看)。最后就是证书至少要使用一个SHA256的指纹与任一个2048位或者更高位的RSA密钥,或者是256位或者更高位的ECC密钥。如果不符合其中一项,请求将被中断并返回nil,简单的说就是下面几个要求:

1.Transport Layer Security协议版本要求TLS1.2以上

2.服务的Ciphers配置要求支持Forward Secrecy等

3.证书签名算法符合ATS要求等

以上就是一次排查服务器的https是否符合ATS规格的方法,当然也可以使用下面的命令行一次性查询:输出结果都是pass的话就说明链接是支持ATS的。

nscurl --ats-diagnostics --verbose https://www.baidu.com

4.由于很多第三方的请求尚未适配https,所以iOS的ATS规格又分为四大类

1.HTTPS Only (只有HTTPS,所有情况下都使用ATS)

顾名思义,这种情况不需要针对某一个域名或者站点做特殊处理,只要服务器的https符合ATS规格就可以了

2.Mix & Match(混合)

这种类型主要某些第三方的请求不支持https或者支持的https不符合ATS的情况:

2.1 在info.plist中添加这个配置项后,ATS当与这个子域交互的时候撤销了必须使用HTTPS的要求(以友盟为例)

2.2 当你请求的第三方服务器支持了https,但是不符合ATS规格,例如SSL版本低于1.2或者FS加密不符合要求的时候,可以做如下配置:

2.3 NSIncludesSubdomains 关键字告诉 App Transport Security 这个“例外”(Exception)适用于这个特定域名的所有子域。这个“例外”(Exception)还进一步通过扩展可接受的密码列表来定义这个域名可以使用不支持forward secrecy( NSExceptionRequiresForwardSecrecy ) 协议的密码。想了解更多关于forward secrecy的信息,推荐去看官方文档Apple's tech note

3. Opt Out(禁用ATS)

这个也是目前做法最广泛的一种方式,把默认的请求的请求方式变成不安全的http,方法上面已经说过了。

4. Opt Out With Exceptions(除特殊情况外,都不使用ATS)

当你的应用撤消了App Transport Security,,但同时定义了一些“例外”(Exception),指定了一个或多个“例外”(Exception)来表明哪些是必须要求 App Transport Security的。

推荐阅读更多精彩内容