Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kitasuke/312700aef3f495fe17877aaacf74e796 to your computer and use it in GitHub Desktop.
Save kitasuke/312700aef3f495fe17877aaacf74e796 to your computer and use it in GitHub Desktop.

概要

iOS9からApp Transport Security(ATS)が追加されました。 ATSとは安全なネットワーク接続を実現するための機能であり、Appleの要件を満たしていない場合は接続失敗という扱いになります。

対応方法

対象となるのは、自社内サーバ、WebView経由、サードパーティライブラリ(SNS、広告、分析など)だと思います。 ATS自体を無効にするのはあまり良いやり方ではないので、これらのドメインをATSの例外に設定するのが一般的なやり方だと思います。

設定方法

設定方法はInfo.plistに指定の情報をセットするだけです。 しかし、プロジェクトのTargetが多かったりConfigurationによって設定を分けたい場合には、Info.plistを個別に用意して管理する必要がありますが、無駄にInfo.plistファイルが増えるので良い方法ではないと思います。

スクリプトでATS設定

そこで、スクリプトを実行して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>

あとは、TargetConfigurationごとにそれぞれ例外を設定するだけです。 スクリプト内では${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コマンドを正しく理解出来ていないだけかもしれません...

Preprocessed-Info.plistを活用する

これで、実行プロジェクトの状態から適切な情報がInfo.plistにセットされますが、別の問題が出てきました。 Configurationなどを変えるとビルド後にInfo.plist自体が編集されるので、ファイルに差分が出てしまいます。

上記のように設定を変えるたびに毎回差分が出るのは邪魔なので、Preprocessed-Info.plistの方を編集することでInfo.plistの差分を出さないようにします。

Preprocessed-Info.plistとは、Build Phaseの1番最初に生成されて、その後に編集された内容もアプリに反映されるplistのことです。 Build SettingsPreprocess Info.plist FileYESにすると生成されます。 このファイルは${TEMP_DIR}以下に生成されるので、編集しても差分が出ることはありません(プロジェクト直下では無いので)。

先ほどのPlistBuddyコマンドは編集するplistを指定することが出来ます。 最終的なコマンドは以下のようになります。

/usr/libexec/PlistBuddy -c Add NSAppTransportSecurity:NSExceptionDomains:foo.com:NSExceptionAllowsInsecureHTTPLoads bool true ${TEMP_DIR}/Preprocessed-Info.plist

まとめ

スクリプトが出来るまで多少時間はかかりましたが、設定しているATSの例外を一元管理出来るので、良い方法ではないかと思います。 特に大規模なプロジェクトだと細かい違いがあるので、スクリプトで処理を判別出来るのは良かったです。

唯一の後悔は、素直にシェルスクリプトで書いてしまったことです。 なぜSwiftで書かなかったのか...

まだATSの対応をされていない方もいらっしゃると思うので、参考になれば幸いです。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment