關於 iOS 10 中 ATS 的問題

weixin_34116110發表於2016-09-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 安全部門對現在的情況也有些內部衝突,所以不排除在正式版中發生改變的可能性。我也會對此繼續關注,並在需要的時候對本文進行更新。如果您發現了下面所述和事實不符的話,也歡迎留言提出,我會進行修正。

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

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

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

對於網頁瀏覽和視訊播放的行為,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 HTTPiOS 10 HTTP備註

NSAllowsArbitraryLoads: NOUIWebView❌❌

WKWebView❌❌預設行為

URLSession❌❌

NSAllowsArbitraryLoads: YESUIWebView✅✅禁用 ATS

WKWebView✅✅稽核時需要說明理由

URLSession✅✅

NSAllowsArbitraryLoads: NO & NSAllowsArbitraryLoadsInWebContent: YESUIWebView❌❌只對網頁內容禁用 ATS

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

URLSession❌❌保證安全性

NSAllowsArbitraryLoads: NO & NSAllowsArbitraryLoadsInWebContent: NOUIWebView❌❌

WKWebView❌❌

URLSession❌❌

NSAllowsArbitraryLoads: YES & NSAllowsArbitraryLoadsInWebContent: NOUIWebView✅❌對於 iOS 10,

WKWebView✅❌NSAllowsArbitraryLoadsInWebContent 存在時忽略 NSAllowsArbitraryLoads 的設定

URLSession✅❌iOS 9 將繼續使用 NSAllowsArbitraryLoads

NSAllowsArbitraryLoads: YES & NSAllowsArbitraryLoadsInWebContent: YESUIWebView✅❌對於 iOS 10,

WKWebView✅✅NSAllowsArbitraryLoadsInWebContent 存在時忽略 NSAllowsArbitraryLoads 的設定

URLSession✅❌iOS 9 將繼續使用 NSAllowsArbitraryLoads

該列表是根據 Apple prerelease 的文件中關於NSAppTransportSecurity和NSAllowsArbitraryLoadsInWebContent部分的描述作出的。現在 (2016.06.17) 的 iOS 10 beta 和 Xcode 8 beta 版本中NSAllowsArbitraryLoadsInWebContent似乎還不能正確工作。在現在的 beta 版中,似乎只要存在NSAllowsArbitraryLoadsInWebContent,不論其設定如何,WKWebView都不能載入。如果這個行為發生了變化,或者上面的列表存在問題,歡迎留言,我會進行更正。

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

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


轉自https://onevcat.com/2016/06/ios-10-ats/

相關文章