首先是还算好的好消息
苹果官方表示:强制使用 HTTPS 的要求将暂时不执行,以便给我们更多的时间来做 HTTPS 的适配工作。具体的执行时间,将在确定后再次发布。因此,我们依然可以在 'xxx-Info.plist' 中设置 'App Transport Security Settings' 的 'Allow Arbitrary Loads' 属性设置为yes,来避开ATS要求。这样我们的应用不再需要任何修改就可访问http的网页。
其次是出来混总要还的
首先我们需要把网站配置成支持HTTPS。
苹果的 ATS (App Transport Security) 政策对于HTTPS的要求,包括:
1. X.509证书必须至少满足下面一种条件:
由根证书是操作系统安装的CA颁发;
由用户或系统管理员信任并安装的根证书颁发;
2. TLS版本必须为TLS 1.2,不使用TLS或使用老版本TLS的连接,访问会失败,基于TLSTool工程可获取服务器支持的TLS相关参数;
连接必须使用AES-128或AES-256对称加密算法,TLS协商算法必须通过ECDHE密钥交换保证完全正向保密(Perfect Forward Secrecy, PFS),ECDHE密钥必须属于下面一种:
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
3. 服务器叶证书必须使用下列的密钥签名:
至少2048位的RSA密钥;
至少256位的ECC密钥;
验证网站是否支持苹果的 ATS 要求
对于OS X v10.11及以上系统,用户可以在终端中使用
/usr/bin/nscurl --ats-diagnostics --verbose https://www.baidu.com
来验证目标网站是否符合 ATS 要求,以及是否需要加入白名单。
此外,腾讯云也提供了验证是否符合ATS要求的验证 SSL 网页。
对于无法支持ATS的网站,尤其是第三方网站的适配方案。
首先配置 'xxx-Info.plist' 对于用户的 API 请求,苹果要求是必须使用 HTTPS 的,特别是当这个服务器是属于你们自己管理的话。那么这就需要服务器的同事尽快配置证书好让服务器支持 HTTPS 访问。如果使用的是第三方的 API,而他们没有提供 HTTPS 支持的话,需要在 NSExceptionDomains 中进行添加。具体的添加方式可以参考官方的 App Transport Security Technote,官方对他进行了具体的说明。
这些都可以在 'xxx-Info.plist' 的 ‘NSAppTransportSecurity’ 中进行配置,具体的内容包括
NSAllowsArbitraryLoads - Bool类型 - 设置YES即可完全关闭ATS,以便支持所有HTTP请求,默认为NO。
NSAllowsArbitraryLoadsInWebContent - Bool类型 - 允许应用浏览网页内容时关闭ATS限制。默认为NO,像是 UIWebView 或 WKWebView 需要访问 HTTP 或者不安全的 HTTPS 时,需要设置为YES来允许访问。
NSAllowsArbitraryLoadsForMedia - Bool类型 - 允许该APP的 AVFoundation 中的 player 可以关闭 ATS 限制。默认为NO,如果媒体内容不支持 HTTPS 可打开该关键字。
NSAllowsLocalNetworking - Bool类型 - 设置本地网络请求不受 ATS 的限制,默认为NO。
NSExceptionDomains - Dictionary类型 - 添加白名单域名,对应不同的白名单中的网址设置他们的安全例外内容。需要例外的域名根地址 (不包括 'http://' 或 'https://' 的头和 '/' ) 作为关键字,Dictionary类型,内容为下面的参数。
NSExceptionMinimumTLSVersion - String类型 - 白名单指定域名支持的TLS版本,苹果要求必须达到TLS 1.2版本,如果你访问的网站仅支持TLS 1.0,那么设置为 'TLSv1.0'。
NSExceptionRequiresForwardSecrecy - Bool类型 - 白名单指定域名是否支持Forward Secrecy,默认值为YES,如果域名不支持完全正向加密,那么设置为NO。具体的加密要求可以阅读上方官方技术文档。
NSExceptionAllowsInsecureHTTPLoads - Bool类型 - 白名单指定域名禁用ATS,而不仅仅只是允许HTTP访问,默认是NO。
NSIncludesSubdomains - Bool类型 - 白名单指定该白名单的相关设置是否同样设置它的子域名,默认为NO。
‘SDWebImage’ 无法下载图片的问题。在设置了白名单后,出现部分网上的图片无法通过 ‘SDWebImage’ 进行下载的问题。解决方法是在下载图片时,设置 ‘options’ 为 ‘SDWebImageAllowInvalidSSLCertificates’ 来允许SDWebImage类访问无效的SSL认证。
[self.headImageView sd_setImageWithURL:[NSURL URLWithString:headImageStr] placeholderImage:kCLDefaultHeadImage options:SDWebImageAllowInvalidSSLCertificates];
‘AFNetworking’ 在 ATS 打开情况下,对于无效证书 (像是自建证书) 和不匹配域名的证书可能会请求失败,那么我们需要修改请求的安全要求,来允许无效证书和不匹配域名的证书。
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
//allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO//如果是需要验证自建证书,需要设置为YES
securityPolicy.allowInvalidCertificates = YES;
//validatesDomainName 是否需要验证域名,默认为YES;
securityPolicy.validatesDomainName = NO;
manager.securityPolicy = securityPolicy;
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager POST:urlString parameters:dic success:finishedBlock failure:failedBlock];
Reference List:
"Supporting App Transport Security", https://developer.apple.com/news/?id=12212016b
"Apple's Information Property List Key Reference", https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html
"苹果ATS(强制HTTPS)审核新政解码", https://yq.aliyun.com/articles/62563
"iOS 中 AFNetworking HTTPS 的使用", http://www.jianshu.com/p/20d5fb4cd76d
"苹果新『应用通信安全』的理解和使用", http://www.cocoachina.com/ios/20150717/12650.html