關於iOS10中ATS的問題

技術小甜發表於2017-11-08

WWDC 15 提出的 ATS (App Transport Security) 是 Apple 在推進網路通訊安全的一個重要方式。在 iOS 9 和 OS X 10.11 中,預設情況下非 HTTPS 的網路訪問是被禁止的。當然,因為這樣的推進影響面非常廣,作為緩衝,我們可以在 Info.plist 中新增 NSAppTransportSecurity 字典並且將 NSAllowsArbitraryLoads 設定為 YES 來禁用 ATS。相信大家都已經對這個非常熟悉了,因為我自己也維護了一些網路相關的框架,所以我還自己準備了一個小指令碼來快速關閉 ATS。

不過,WWDC 16 中,Apple 表示將繼續在 iOS 10 和 macOS 10.12 裡收緊對普通 HTTP 的訪問限制。從 2017 年 1 月 1 日起,所有的新提交 app 預設是不允許使用 NSAllowsArbitraryLoads 來繞過 ATS 限制的,也就是說,我們最好保證 app 的所有網路請求都是 HTTPS 加密的,否則可能會在應用稽核時遇到麻煩。

本文寫作的時間點 (2016 年 6 月 17 日),這方面的相關規定和幾個事實如下。但是似乎 Apple 安全部門對現在的情況也有些內部衝突,所以不排除在正式版中發生改變的可能性。我也會對此繼續關注,並在需要的時候對本文進行更新。如果您發現了下面所述和事實不符的話,也歡迎留言提出,我會進行修正。

  1. 預設情況下你的 app 可以訪問加密足夠強 (TLS v1.2 以上,AES-128 和 SHA-2 以及 ECDHC 等) 的 HTTPS 內容。這對所有的網路請求都有效,包括 NSURLSessionUIWebView 以及 WKWebView 等。

  2. 你依然可以新增 NSAllowsArbitraryLoads 為 YES 來禁用 ATS,不過如果你這麼做的話,需要在提交 app 時進行說明,為什麼需要訪問非 HTTPS 內容。一般來說,可能類似瀏覽器類的 app 比較容易能通過。

  3. 相比於使用 NSAllowsArbitraryLoads 將全部 HTTP 內容開放,選擇使用 NSExceptionDomains 來針對特定的域名開放 HTTP 應該要相對容易過稽核。“需要訪問的域名是第三方伺服器,他們沒有進行 HTTPS 對應”會是稽核時的一個可選理由,但是這應該只需要針對特定域名,而非全面開放。如果訪問的是自己的伺服器的話,可能這個理由會無法通過。

  4. 對於網頁瀏覽和視訊播放的行為,iOS 10 中新加入了 NSAllowsArbitraryLoadsInWebContent 鍵。通過將它設定為 YES,可以讓你的 app 中的 WKWebView 和使用 AVFoundation 播放的線上視訊不受 ATS 的限制。這也應該是絕大多數使用了相關特性的 app 的選擇。但是壞訊息是這個鍵在 iOS 9 中並不會起作用。

總結一下就是,對於 API 請求,基本上是必須使用 HTTPS 的,特別是如果你們自己可以管理伺服器的話。可能需要後端的同學儘快升級到 HTTPS (不過話說雖然是用 Let`s Encrypt 的,我一個個人部落格都啟用 HTTPS 了,作為 API 的使用者伺服器,還不開 HTTPS 真有點說不過去)。如果你的 app 只支援 iOS 10,並且有使用者可以自由輸入網址進行瀏覽的功能,或者是線上視訊音訊播放功能的話,簡單地加入 NSAllowsArbitraryLoadsInWebContent,並且將元件換成 WKWebKit或者 AVFoundation 就可以了。如果你還需要支援 iOS 9,並且需要訪問網頁和視訊的話,可能只能去開啟 NSAllowsArbitraryLoads 然後提交時進行說明,並且看 Apple 稽核員的臉色決定讓不讓通過了。除了 WKWebKit 以外,另外一個訪問網頁的選擇是使用 SFSafariViewController。因為其實 SFSafariViewController 就是一個獨立於 app 的 Safari 程式,所以它完全不受 ATS 的限制。

另外,當 NSAllowsArbitraryLoads 和 NSAllowsArbitraryLoadsInWebContent 同時存在時,根據系統不同,表現的行為也會不一樣。簡單說,iOS 9 只看 NSAllowsArbitraryLoads,而 iOS 10 會先看 NSAllowsArbitraryLoadsInWebContent。在 iOS 10 中,要是 NSAllowsArbitraryLoadsInWebContent 存在的話,就忽略掉 NSAllowsArbitraryLoads,如果它不存在,則遵循 NSAllowsArbitraryLoads 的設定。說起來可能有點複雜,我在這裡總結了一下根據 NSAppTransportSecurity 中設定條件不同,所對應的系統版本和請求元件的行為的不同,可以作為你設定這個字典時的參考。

ATS 設定 使用的元件 iOS 9 HTTP iOS 10 HTTP 備註
NSAllowsArbitraryLoads: NO UIWebView

WKWebView 預設行為

URLSession
NSAllowsArbitraryLoads: YES UIWebView 禁用 ATS

WKWebView 稽核時需要說明理由

URLSession
NSAllowsArbitraryLoads: NO & NSAllowsArbitraryLoadsInWebContent: YES UIWebView 只對網頁內容禁用 ATS

WKWebView 對於大多數 app 的推薦做法,

URLSession 保證安全性
NSAllowsArbitraryLoads: NO & NSAllowsArbitraryLoadsInWebContent: NO UIWebView

WKWebView

URLSession
NSAllowsArbitraryLoads: YES & NSAllowsArbitraryLoadsInWebContent: NO UIWebView 對於 iOS 10,

WKWebView NSAllowsArbitraryLoadsInWebContent 存在時忽略 NSAllowsArbitraryLoads 的設定

URLSession iOS 9 將繼續使用 NSAllowsArbitraryLoads
NSAllowsArbitraryLoads: YES & NSAllowsArbitraryLoadsInWebContent: YES UIWebView 對於 iOS 10,

WKWebView NSAllowsArbitraryLoadsInWebContent 存在時忽略 NSAllowsArbitraryLoads 的設定

URLSession iOS 9 將繼續使用 NSAllowsArbitraryLoads

該列表是根據 Apple prerelease 的文件中關於 NSAppTransportSecurity 和 NSAllowsArbitraryLoadsInWebContent 部分的描述作出的。如果您發現這個行為發生了變化,或者上面的列表存在問題,歡迎留言,我會進行更正。

關於 UIWebView 是否也可以在 NSAllowsArbitraryLoadsInWebContent 為 YES 時訪問 HTTP,Apple 內部似乎也在爭論,但是個人認為是時候淘汰 UIWebView 了。如果沒有特殊的什麼需求的話,儘早將 UIWebView 全部換為 WkWebView 會是明智的選擇。

不得不說,Apple 使用自己現在的強勢地位,在推動技術進步上的做的努力是有目共睹的。不論是前幾天強制支援 IPv6,還是現在的 HTTPS,其實都不是很容易就能作出的決定。而為使用者構建一個更安全的使用環境,可能不僅是 Apple 單方面可以做的,也是需要開發者來配合的一件事情。儘快適配更進步和安全的使用方式,會是一件雙贏的事情。

本文轉自ljianbing51CTO部落格,原文連結: http://blog.51cto.com/ljianbing/1876020,如需轉載請自行聯絡原作者


相關文章