iOS 10从2017年1月1日起苹果不允许我们通过这个方法跳过ATS,也就是说强制我们用HTTPS,如果不这样的话提交App可能会被拒*。但是我们可以通过NSExceptionDomains来针对特定的域名开放HTTP可以容易通过审核。)

由于离2017年越来越近,关于苹果强制我们使用HTTPS,我搜集了一下资料如下:

%title插图%num
Apple官方文档

WWDC Session: “Networking with NSURLSession” session( 【WWDC 2015 session 703, “Privacy and Your App” O网页链接 】, 时间在30:18左右)

%title插图%num

%title插图%num

%title插图%num

即使你的应用使用的是:你没有权限控制的CDN (Content Delivery Network),而且它不支持HTTPS!

也别担心,Apple都替你考虑好了:

正如你在上图中看到的:苹果官方提供了一些可选配置项来决定是否开启ATS模式,也就是可以选择开启或者不开启。

开发者可以针对某些确定的URL不使用ATS,这需要在工程中的info.plist中标记NSExceptionDomains。在NSExceptionDomains字典中,可以显式的指定一些不使用ATS的URL。这些你可以使用的例子可以是:

NSIncludesSubdomains

NSExceptionAllowInsecureHTTPLoads

NSExceptionRequiresForwardSecrecy

NSExceptionMinimumTLSVersion

NSThirdPartyExceptionAllowsInsecureHTTPLoads

NSThirdPartyExceptionMinimumTLSVersion

NSThirdPartyExceptionRequiresForwardSecrecy

这些关键字使我们可以更加细致的设置针对不使用ATS的域名情况下禁用ATS或者一些特殊的ATS选项。

你可能注意到一些关键字像是使用了一些其他关键字中的词但是在前面加上了”ThirdParty”字样,比如列表里*后三个:

NSThirdPartyExceptionAllowsInsecureHTTPLoads

NSThirdPartyExceptionMinimumTLSVersion

NSThirdPartyExceptionRequiresForwardSecrecy

在功能上,这些关键字与不含有”ThirdParty”的关键字有同样的效果。而且实际运行中所调用的代码将会完全忽略是否使用”ThirdParty”关键字。你应该使用适用于你的场景的关键字而不必过多考虑这些。

关于App Transport Security,每个应用都属于4个大类当中的一类。我们来看看每一个大类都是怎样影响应用的。

— 分类名 解释
1. HTTPS Only (只有HTTPS,所有情况下都使用ATS) 如果你的应用只基于支持HTTPS的服务器,你的应用不需要做任何改变。但是,注意App Transport Security要求TLS 1.2,而且它要求站点使用支持forward secrecy协议的密码。证书也要求是符合ATS规格的。因此慎重检查与你的应用交互的服务器是不是符合ATS的要求。
2. Mix & Match(混合) 如果你的服务器不符合ATS要求,你需要在你的应用的 Info.plist 文件中说明哪些地址是不符合ATS要求的。
3. Opt Out(禁用ATS) 如果你在创建一个网页浏览器,因为你不能确定用户将要访问哪个网页,也就不可能指明这些网页是否支持ATS要求且在HTTPS上传输。在这种情况下,只能配置为禁用ATS。
4. Opt Out With Exceptions(除特殊情况外,都不使用ATS) 如果想禁用ATS的同时又想定义一些例外。这个应用场景是当你的应用需要从很多不符合ATS要求的服务器上取数据,但是也要与一个你可控的API(符合ATS要求)交互。在这种情况下,需要在应用的 Info.plist 文件中配置为允许所有请求,但是你也指定了一个或多个例外来表明哪些请求是必须符合ATS的要求。
下面分别做一下介绍:

1.HTTPS Only (只有HTTPS,所有情况下都使用ATS)
如果你的应用只基于支持HTTPS的服务器,那么你太幸运了。你的应用不需要做任何改变。

唯一需要做的事情就是使用 NSURLSession 。如果你的开发目标是iOS 9或者 OS X EI Capitan之后,ATS 的*佳实践将会应用到所有基于 NSURLSession 的网络。

但也有人遇到过这样的疑惑:服务器已支持TLS 1.2 SSL ,但iOS9上还是不行,还要进行本文提出的适配操作。

那是因为:要注意 App Transport Security 要求 TLS 1.2,而且它要求站点使用支持forward secrecy协议的密码。证书也要求是符合ATS规格的,ATS只信任知名CA颁发的证书,小公司所使用的 self signed certificate,还是会被ATS拦截。因此慎重检查与你的应用交互的服务器是不是符合ATS的要求非常重要。对此,建议使用下文中给出的NSExceptionDomains,并将你们公司的域名挂在下面。

官方文档 App Transport Security Technote 对CA颁发的证书要求:

Certificates must be signed using a SHA256 or better signature hash algorithm, with either a 2048 bit or greater RSA key or a 256 bit or greater Elliptic-Curve (ECC) key. Invalid certificates result in a hard failure and no connection

2.Mix & Match(混合)
如果你的服务器不符合ATS要求。

比如当你遇到以下三个不符合 ATS 要求的服务器的域名时:

api.insecuredomain.com
cdn.domain.com
thatotherdomain.com
你可以分别设置如下:

api.insecuredomain.com

Info.plist 配置中的XML源码如下所示:

<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>api.insecuredomain.com</key>
<dict>

<!–允许App进行不安全的HTTP请求–>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>

<!–适用于这个特定域名下的所有子域–>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
在 plist 文件里显示如下:

 

我们定义的*个“例外”(Exception)告诉ATS当与这个子域交互的时候撤销了必须使用HTTPS的要求。注意这个仅仅针对在“例外”(Exception)中声明了的子域。非常重要的一点是要理解NSExceptionAllowsInsecureHTTPLoads关键字并不仅仅只是与使用HTTPS相关。这个“例外”(Exception)指明了对于那个域名,所有的App Transport Security的要求都被撤销了。

cdn.domain.com Info.plist 配置中的XML源码如下所示:

<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>cdn.somedomain.com</key>
<dict>
<key>NSThirdPartyExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
</dict>
</dict>
在 plist 文件里显示如下:

 

很可能你的应用是与一个支持HTTPS传输数据的服务器交互,但是并没有使用TLS 1.2或更高。在这种情况下,你定义一个“例外”(Exception),它指明应该使用的*小的TLS的版本。这比完全撤销那个域名的App Transport Security要更好更安全。

thatotherdomain.com

Info.plist 配置中的XML源码如下所示:

<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>thatotherdomain.com</key>
<dict>
<!–适用于这个特定域名下的所有子域–>
<key>NSIncludesSubdomains</key>
<true/>
<!–扩展可接受的密码列表:这个域名可以使用不支持 forward secrecy 协议的密码–>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<!–允许App进行不安全的HTTP请求–>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<!–在这里声明所支持的 TLS *低版本–>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
</dict>
</dict>
在 plist 文件里显示如下:

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

如果你的App中同时用到了这三个域名,那么应该是这样:

<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>api.insecuredomain.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<false/>
</dict>
<key>cdn.somedomain.com</key>
<dict>
<key>NSThirdPartyExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
<key>thatotherdomain.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
</dict>
</dict>

3. Opt Out(禁用ATS)
上面是比较严谨的做法,指定了能访问哪些特定的HTTP。当然也有暴力的做法: 彻底倒退回不安全的HTTP网络请求,能任意进行HTTP请求,比如你在开发一款浏览器App,或者你想偷懒,或者后台想偷懒,或者公司不给你升级服务器。。。

你可以在Info.plist 配置中改用下面的XML源码:

<key>NSAppTransportSecurity</key>
<dict>
<!–彻底倒退回不安全的HTTP网络请求,能任意进行HTTP请求 (不建议这样做)–>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
在 plist 文件里显示如下:

4. Opt Out With Exceptions(除特殊情况外,都不使用ATS)
上面已经介绍了三种情景,还有一种可能你也会遇到:

当你禁用ATS的同时又想定义一些“例外”(Exception)。这个应用场景是当你的应用需要从很多不符合ATS要求的服务器上取数据,但是也要与一个你可控的API(符合ATS要求)交互。在这种情况下,在应用的Info.plist文件中配置为允许所有请求,但是你也指定了一个或多个“例外”(Exception)来表明哪些地址是必须符合 App Transport Security 要求的。下面是Info.plist文件应该会有的内容:

<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>api.tutsplus.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<false/>
</dict>
</dict>
</dict>
在 plist 文件里显示如下:

【注:以上在Info.plist配置中的做法已经验证可行,但目前Apple的prerelease版本的官方文档并未提及Info.plist中配置的代码,我将密切关注官方文档,如有提及,再来更新本文 .你若发现官方文档有提及了,也可在微博@iOS程序犭袁通知下我。】(官方文档已经有阐述)

Certificate Transparency
虽然ATS大多数安全特性都是默认可用的,Certificate Transparency 是必须设置的。如果你有支持Certificate Transparency的证书,你可以检查NSRequiresCertificateTransparency关键字来使用Certificate Transparency。再次强调,如果你的证书不支持Certificate Transparency,此项需要设置为不可用。

如果需要调试一些由于采用了ATS而产生的问题,需要设置CFNETWORK_DIAGNOSTICS为1,这样就会打印出包含被访问的URL和ATS错误在内的NSURLSession错误信息。要确保处理了遇到的所有的错误消息,这样才能使ATS易于提高可靠性和扩展性。

原文地址:https://github.com/ChenYilong/iOS9AdaptationTips#1-demo1_ios9%E7%BD%91%E7%BB%9C%E9%80%82%E9%85%8D_ats%E6%94%B9%E7%94%A8%E6%9B%B4%E5%AE%89%E5%85%A8%E7%9A%84https