WWDC2016にてATS(App Transport Security)の必須化がアナウンスされました。しかしご存知の通り、必須化は延期されました。また、iOS10で新たなATSの設定を行うInfo.plistのキーが導入されましたが、iOS10のマイナーバージョンごとに仕様が異なります。このLTでは、制度も情報も仕様も混乱しているATSを5分でマスターしていただくことに挑戦します。
忙しい人のためのApp Transport Security
日本語で try! Swift のLive Blogを書いています。
京都から来ました。
京都には日本の文化や歴史を代表するものがたくさんあります。 この一面に金箔が貼られ建物(Pavilion)もその一つです。金閣と言います。 雪の中で輝いていて美しいですね!
実は私の先祖が建てたそうです。 600年前に100億円もかかったそうです。 お金持ちですね。
子孫の私はお金持ちではありませんが、ゴールドのMacBookを買いました。 こちらも、とても美しいですね。 気に入っています。
私は “株式会社はてな” のiOSデベロッパーです。 日本における代表的なソーシャルブックマークサービスである “はてなブックマーク” のアプリを開発しています。
今日は、AppTransportSecurityについてお話します。
昨年のWWDCでApp Transport Securityの必須化が発表されました
ところでApp Transport Security、ATSとは何でしょう。 これはiOS9で登場した機能です。
ATSはアプリを作成したときからデフォルトで有効になっています
ATSは、アプリが行うサーバーとの通信を 安全性の高いhttps だけに限定します。 それ以外の通信はブロックして、アプリの安全性を高めます。
ところで、 httpsに 安全なも と 安全でないもの が ある というのはどういうことでしょうか?
httpsにはハッシュアルゴリズムや電子署名、暗号化などの技術の上に成り立っています。
Webサーバーが提供するこれらの技術が、古いものや、強度の弱いものであった場合、 https通信の安全性が低下してしまいます。
そこでATSはある基準以上の 安全性を満たしたhttpsのみ 通信できるようにします。 詳しい基準については、AppleのInformation Property List Key Referenceを御覧ください。
また、nscurlコマンドのats diagnosticsを利用すれば、 あるURLがATSの基準を満たしているかどうかを 調べることが出来ます。
apple.comで試すと、ResultがPASSになります。
swift.orgで試すと、ResultはFAILになります。 httpsなのにATSの条件を満たしていないことがわかります
では、httpや、swift.orgなどの安全性の低いhttpsに接続したい場合は どうしたら良いでしょうか
ATSのすべての機能を無効化する NSAllowsArbitraryLoads が用意されています。 Info.plistで設定することが出来ます。
また、特定のドメインでのみATSを無効化すればよいのであれば、 NSExceptionDomainsを使って 特定のドメインのみをATSの例外にすることが出来ます。
そして昨年のWWDCでは新しいオプションも登場しました
AVFoundationの通信についてATSの制限を解除するNSAllowsArbitraryLoadsForMedia、
そして UIWebViewやWKWebViewの通信についてATSの制限を解除する NSAllowsArbitraryLoadsInWebContent です。
さらに iOS10が実際にリリースされたときには、 ローカルのホストに対する通信についてATSの制限を解除する NSAllowsLocalNetworking も加わっていました。
iOS10 以降はこれらのオプションの中から適切なものを選ぶことが求められます。
私のアプリは、 ユーザーがブックマークしたWebサイトを表示します。
サイトはhttpかもしれないし、httpsかもしれません。どちらも表示できるべきです。
そのためにはATSを無効化する必要がありますが、 WebViewが接続できれば良いので、ATSをすべて無効化する必要はありません。
そこで私はWebViewだけを対象にATSを無効化する NSAllowsArbitraryLoadsInWebContent を試してみました すると厄介な問題を発見したのでご紹介します
これは私がATSの仕様を説明するためによく利用する図です。
http、安全でないhttps、安全なhttpsに対して、 WKWebView、UIWebView、NSURLSessionが それぞれ接続可能かどうか この図を使って説明したいと思います。
まず、なにも設定しておらずATSが有効になっている時 安全なHTTPSに対してのみ通信が出来ます。
NSAllowsArbitraryLoadsはすべての通信が可能になります。
では、次に NSAllowsArbitraryLoadsInWebContent を使ってみましょう。
@niwatako use for your blog if you want #tryswiftconf pic.twitter.com/sED58vr6AP
— Daiki Matsudate (@d_date) 2017年3月3日
(Thanks @d_date!!)
こうなります。
WKWebViewとUIWebViewから HTTPの通信が可能になりました。
ところが、安全性の低いHTTPSには接続できないままです。 これは仕様でしょうか?
。。。これは、 iOS10.0 の場合です。
iOS10.2 では、UIWebViewが 安全性の低いHTTPSに対して通信可能になりました。
NSAllowsArbitraryLoadsInWebContentを利用しても 依然としてWKWebViewが安全性の低いHTTPSに接続できないのは バグです。
これでは、NSAllowsArbitraryLoadsInWebContentは WebViewのATSを無効にするもの、というよりは “HTTP通信を許可” するものであって 言ってみれば AllowsHTTPLoadsInWebContent ということになります。
このままではWKWebViewを使っている私のアプリは swift.org を表示する事ができません どうしたら良いでしょう
それに、iOS10.1以下と
iOS10.2以降で UIWebViewの挙動が変化するのもとても厄介です。 私たちはどうしたら良いのでしょうか。
ところで、end of 2016から必須と言われたATSですが、
結局必須化は延期されました。
ですから、 現在はひとまず NSAllowsArbitraryLoads を使えば良いという事になります。 いろいろありましたが、結論としては、何もしなくて良いという答えになってしまいました。
私が今日お伝えしたかった大切なことは、みなさんがATSに対応する際の注意事項です。
ATSには今日ご紹介したようなバグがあります。 ですから、Appleのドキュメントを信じるだけではダメです。実際にはバグでうまく動かないかもしれません。 また、実機でうまく動いたからといってそれがあるべき形で実装できているとも限りません。バグによってたまたまうまく動いているだけで、バグが直ると正しく動かなくなるかもしれません。 仕様と、実際の挙動の、両方を確認しましょう。 実際の挙動を確認するためには、iOSのマイナーバージョンごとに動作確認をしたほうが良いでしょう。
必須化(Enforcement)は延期されましたが、対応する際は今日お話したことを思い出していただきたいと思います
私の話は以上です。ご清聴ありがとうございました。