webview_flutterで特定のURLを表示できない問題が発生しました。
iOSだけです。Androidは問題ありません。
問題のURL:https://opac.lib.city.yokohama.lg.jp/opac/
webview_flutterのReadmeで書いてある「https://flutter.dev」や自分のブログ「https://take424.dev」など、いくつかのURLを試した限りは問題なし。
この「opac.lib.city.yokohama.lg.jp」だけ、WebView.onProgressが100%になったあと、WebView.onPageFinishedが呼び出されず、ページが表示されません。
横浜図書館利用状況アプリでflutter_webviewを使っていた際やそこからwebview_flutterに移行した際は、特に問題なく同URLを表示できていたのでかなり頭を抱えました。解決まで2時間ぐらいかかりました。
原因:App Transport Security(ATS)
色々調べているうちに、webview_flutterの使い方ではなく、何か設定の問題じゃないかと思って、うまくいっている横浜図書館利用状況アプリの「ios/Runner/Info.plist」とdiffを取ってみると以下の違いがありました。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
どうやら「App Transport Security(ATS)」が原因の可能性が高そうです。
ATSとは、iOSで組み込まれている「サーバとアプリケーション間でセキュアな通信を保証するための機能」です。
ATSはデフォルトで有効となっており、Appleが推奨する条件を満たすHTTPS通信のみ許可されます。満たさないHTTPS通信やHTTP通信は不許可となり、通信できません。
Appleが推奨する条件は以下の通りです。

公式だと以下のページに記載がありました。

裏取り:「TLS1.0」が有効になっている
早速、「opac.lib.city.yokohama.lg.jp」をSSL Server Testサイトで調べてみると、「TLS1.0」が有効となっていることがわかりました。
上記の通り、Apple推奨条件としては「TLS1.2以上」が定められているので、おそらくこれが原因でATSによって通信がブロックされていると思われます。

SSL Server Testの結果は以下の通りです。
対策:Info.plistにATS例外設定を追加
本来であれば、サーバーのセキュリティを向上させて対策したいところですが、今回は自分のサイトではなく、サーバー側の設定変更はできないため、ATSの例外設定を行うことで回避することにしました。
色々と細かく設定できるようですが、とりあえず動けばよいので、flutter_webview_pluginで推奨している以下の設定をInfo.plistに追記しました。
<key>LSRequiresIPhoneOS</key>
<true/>
<!-- ここから追加 -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
<!-- ここまで追加 -->
<key>UILaunchStoryboardName</key>
この設定を入れると、アプリ審査時にATS除外の理由を問われることがあるということですが、リリース済みの「横浜市立図書館利用状況」アプリを40回ぐらいアップデートしていますが、今のところ聞かれたことはありません。
セキュリティ対策として細かく設定した方が良いのは確かですが、アプリ審査でそこまでシビアに見られることはないようです。
結果:表示確認完了
ATSの例外設定をして、webview_flutterで問題のURL「https://opac.lib.city.yokohama.lg.jp/opac/?LANG=ja」を表示することができました!

おわりに
約2年前にflutter_webview_pluginを追加した際、確かにこのATS例外設定を追加しましたが、何も考えずにマニュアル通りにやって動いてしまっていたので気にも留めていませんでした。
また、セキュリティ対策をしっかりやっているサーバーであれば、当然このATS例外設定は不要なので、ATSの存在を知らなくても問題ないままいけることも多いと思います。
しかし、今回のようにたまたまwebviewで表示しようとしたサイトがATS条件を満たしてなかった場合 、突然ページが表示できなくてビックリすることになるため、頭の片隅に置いておいた方が良さそうです。
というか、flutter_webview_pluginのようにwebview_flutterもReadmeに書いてほしいですよね。。


コメント