iOS9のWebviewでNSURLErrorDomainとなる場合の対処法(ATS)


##追記(2015/09/14)

ATSのデフォルトの挙動がiOS9 beta5から変更されていました。

```
All connections using the NSURLConnection, CFURL, or NSURLSession APIs use App Transport Security default behavior in apps built for iOS 9.0 or later, and OS X 10.11 or later. Connections that do not follow the requirements will fail. 
```

[App Transport Security Technote - Apple Developer](https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/index.html#//apple_ref/doc/uid/TP40016240-CH1-SW3)

これによりATSが適用されるのはiOS9.0向けにビルドしたアプリ(Xcode7.0、Base SDK9.0以降)となり、デフォルトの挙動は変わらずにONとなっています。
なので、Base SDK9.0未満でのビルドの場合はATSは適用されず、これまで通りの通信が可能です。

試しにSSL未対応ページを下記の2環境で表示してみたところ、下記結果となりました。

__環境1__

* iOS9.0 GM seed
* Xcode 7.0 GM seed (Base SDK9.0)

`結果 : ATSが有効となり、SSL未対応のページは表示不可`

__環境2__

* iOS9.0 GM seed
* Xcode 6.3 (Base SDK8.3)

`結果 : SSL未対応のページでも表示可`

これによって既存のアプリはそのままの動作をしてくれるようになったので、とりあえずは焦って対応を迫られることはなくなりました。

##はじめに

とあるアプリの動作検証をiOS9で行ったところ、UIWebviewにてページの読み込みができなくなる現象が起こったので、対処法を調べてみました。

動作環境

* iOS9 beta3
* Xcode7.0 beta3

あるURLをWebviewにて読み込んだところ、下記エラーが出ていました。
(便宜上、URLを`http://hogehoge.com`としています。)

```
Error Domain=NSURLErrorDomain Code=-1022 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection." UserInfo=0x7fa3ba101340 {NSUnderlyingError=0x7fa3b86f2b00 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.", NSErrorFailingURLStringKey=http://hogehoge.com, NSErrorFailingURLKey=http://hogehoge.com, NSLocalizedDescription=The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.}
```

```
The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.
```

という部分が非常に意味深です。

##App Transport Security policy (ATS)

公式ドキュメントの一部を抜粋すると、iOS9からアプリとWEB間の通信をセキュアなものを推奨するようになったとあります。(デフォルト設定 : TLS v1.2)

```
App Transport Security is a feature that requires secure connections between an app and web services. The default connection requirements conform to the best practices for secure connections. Apps can override the default behavior and turn off App Transport Security.

App Transport Security is available on iOS 9.0 or later, and on OS X 10.11 and later.
```

* [App Transport Security Technote - Apple Developer](https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/)

そのため、デフォルト設定のままだとHTTPでの通信はできなくなっています。
(HTTPSでの通信に強制的に置き換わる)
通信できるようにするにはいくつか方法がありますが、下記に紹介していきます。

##1.参照先WEBサイトをSSL通信に対応する(推奨)

いろいろと大変ですが、これが一番推奨される対応方法です。
自社で管理しているWEBサイトなどであれば、今後の事も見据えて対応することをお勧めします。

##2.アプリのATSを変更する

外部サイトなどを表示するアプリの場合、1の対応は難しいため、
アプリの設定を変更して表示する方法があります。

やり方としては2パターンあり、

* ATS設定を無効化する
* ドメインレベルでATS設定を振り分ける

### ATS設定を無効化する

アプリ内のInfo.plistを編集し、`NSAllowsArbitraryLoads`を`YES`とするとATSは無効化されます。

![スクリーンショット 2015-07-23 19.33.36.png](https://qiita-image-store.s3.amazonaws.com/0/31823/41fe2406-4b27-c0ad-3319-431d8a3c6496.png "スクリーンショット 2015-07-23 19.33.36.png")

勿論、非推奨なため、今後Appleの申請周りに影響が出てくる可能性も考えられます。

### ドメインレベルでATS設定を振り分ける

こちらもアプリ内のInfo.plistを編集し、ドメインごとにポリシーを設定します。

![スクリーンショット 2015-07-23 19.40.07.png](https://qiita-image-store.s3.amazonaws.com/0/31823/e5d49ad1-770b-e3b1-bf85-a30ec7e84d63.png "スクリーンショット 2015-07-23 19.40.07.png")

スクリーンショットでは`hogehoge.com`に対して`NSTemporaryExceptionAllowsInsecureHTTPLoads`というパラメーターをYESにすることでセキュアでない通信を許可しています。

その他のパラメーターとして下記があります。

* NSExceptionMinimumTLSVersion
* NSExceptionRequiresForwardSecrecy
* NSExceptionAllowsInsecureHTTPLoads
* NSRequiresCertificateTransparency
* NSIncludesSubdomains
* NSThirdPartyExceptionMinimumTLSVersion
* NSThirdPartyExceptionRequiresForwardSecrecy
* NSThirdPartyExceptionAllowsInsecureHTTPLoads

詳しくは[こちら - Apple Developer](https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/)

##おわりに

今回紹介したApp Transport Security policy (ATS)についてはWebviewのリクエストのみでなくNSURLRequestやCFNetworkなどの通信全般が対象になっているため、
APIなどもセキュアな通信が求められるようになってきます。

大方の対象はとりあえずでATS無効化としちゃいそうですが、今後ATS無効化しているアプリは審査通しませんとかAppleさんが言い出すといろいろと大変なことになりそうです。

(beta版の情報のため、製品版とは異なる可能性があります)

##参考資料

* [App Transport Security Technote - Apple Developer](https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/)