iOS9からApp Transport Security(ATS)が追加されました。 ATSとは安全なネットワーク接続を実現するための機能であり、Appleの要件を満たしていない場合は接続失敗という扱いになります。
対象となるのは、自社内サーバ、WebView経由、サードパーティライブラリ(SNS、広告、分析など)だと思います。 ATS自体を無効にするのはあまり良いやり方ではないので、これらのドメインをATSの例外に設定するのが一般的なやり方だと思います。
設定方法はInfo.plist
に指定の情報をセットするだけです。 しかし、プロジェクトのTarget
が多かったりConfiguration
によって設定を分けたい場合には、Info.plist
を個別に用意して管理する必要がありますが、無駄にInfo.plist
ファイルが増えるので良い方法ではないと思います。
そこで、スクリプトを実行してATSに必要な情報をInfo.plist
にセットしてみました。
PlistBuddy
コマンドを使えばplist
を編集できます。 Build Phase
でスクリプトを毎回実行して、Info.plist
にATS対応の情報を追加しています。
HTTP通信のfoo.com
ドメインをATSの例外にするコマンドは以下のようになります。
/usr/libexec/PlistBuddy -c Add NSAppTransportSecurity:NSExceptionDomains:foo.com:NSExceptionAllowsInsecureHTTPLoads bool true
上記のコマンドを実行すると、Info.plist
に以下のように登録されます。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>foo.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
あとは、Target
やConfiguration
ごとにそれぞれ例外を設定するだけです。
スクリプト内では${PRODUCT_NAME}
でTarget
、${CONFIGURATION}
でConfiguration
を取得出来るので、処理を分岐させて適切なドメインにATSの例外設定を実行すれば完了です。
今回対応したアプリはTarget
で本番・開発環境を切り分けれたので、以下のようになりました。
case ${PRODUCT_NAME} in
"JP DEV")
`/usr/libexec/PlistBuddy -c Add NSAppTransportSecurity:NSExceptionDomains:dev.foo.co.jp:NSExceptionAllowsInsecureHTTPLoads bool true`;;
"JP Production")
`/usr/libexec/PlistBuddy -c Add NSAppTransportSecurity:NSExceptionDomains:foo.co.jp:NSExceptionAllowsInsecureHTTPLoads bool true`;;
"US DEV")
`/usr/libexec/PlistBuddy -c Add NSAppTransportSecurity:NSExceptionDomains:dev.foo.com:NSExceptionAllowsInsecureHTTPLoads bool true`;;
"US Production")
`/usr/libexec/PlistBuddy -c Add NSAppTransportSecurity:NSExceptionDomains:foo.com:NSExceptionAllowsInsecureHTTPLoads bool true`;;
esac
余談ですがPlistBuddy
コマンドのAdd
について、既に存在しているエントリをAdd
しようとするとエラーになるので、一度Delete
してからAdd
するようにしています。 PlistBuddy
コマンドを正しく理解出来ていないだけかもしれません...
これで、実行プロジェクトの状態から適切な情報がInfo.plist
にセットされますが、別の問題が出てきました。 Configuration
などを変えるとビルド後にInfo.plist
自体が編集されるので、ファイルに差分が出てしまいます。
上記のように設定を変えるたびに毎回差分が出るのは邪魔なので、Preprocessed-Info.plist
の方を編集することでInfo.plist
の差分を出さないようにします。
Preprocessed-Info.plist
とは、Build Phase
の1番最初に生成されて、その後に編集された内容もアプリに反映されるplistのことです。 Build Settings
のPreprocess Info.plist File
をYES
にすると生成されます。 このファイルは${TEMP_DIR}
以下に生成されるので、編集しても差分が出ることはありません(プロジェクト直下では無いので)。
先ほどのPlistBuddy
コマンドは編集するplistを指定することが出来ます。 最終的なコマンドは以下のようになります。
/usr/libexec/PlistBuddy -c Add NSAppTransportSecurity:NSExceptionDomains:foo.com:NSExceptionAllowsInsecureHTTPLoads bool true ${TEMP_DIR}/Preprocessed-Info.plist
スクリプトが出来るまで多少時間はかかりましたが、設定しているATSの例外を一元管理出来るので、良い方法ではないかと思います。 特に大規模なプロジェクトだと細かい違いがあるので、スクリプトで処理を判別出来るのは良かったです。
唯一の後悔は、素直にシェルスクリプトで書いてしまったことです。 なぜSwiftで書かなかったのか...
まだATSの対応をされていない方もいらっしゃると思うので、参考になれば幸いです。