Introduction
相互 TLS の検証作業をしている時、Android 側の検証が上手くいかなくて、network-security-config
によってカスタムの CA を読み込ませようと思っていた。
そうしたら、全然動かないから、本当に network-security-config
の設定効いている?って思い、usesCleartextTraffic="false"
にしたところ、何事もなく動いて「はぁ?」と思ったのが発端。
非 HTTPS の遮断について、各 OS の取り組みが下記
- iOS
- App Transport Security (ATS)
- iOS 9.0 と macOS 10.11 以降、
NSURLSession
を使った全ての HTTP 通信に対して App Transport Security (ATS) を適用。 - 2016年発表、2017年1月1日適用
- iOS 9.0 と macOS 10.11 以降、
- App Transport Security (ATS)
- Android
- usesCleartextTraffic
- Android 9.0 (Pie) からデフォルトで無効 (つまり平文の HTTP は許可しない)
- デフォルト値は、API レベル 27 以前をターゲットとしているアプリの場合
true
、API レベル 28 以降をターゲットとしているアプリの場合false
- usesCleartextTraffic
この挙動に振り回されてので忘備録。
What happend?
結論は、使っている http 通信パッケージと flutter のバージョンの問題。
http 通信パッケージの問題
dart/Flutter では http 関係の通信パッケージは結構多くて、その中でも自分は
- dart:io (標準パッケージ)
- http (https://pub.dev/packages/http)
を使っている。
で、この二つは dart で実装された非ネイティブなコードになっており、これが原因。
というのも、ATS にしても usesCleartextTraffic にしても、これらが作動するのはネイティブ API を使った場合。
上の ATS の説明にもあるように 「NSURLSession
を使った」、とあるようにネイティブ実装ではない、上記の 2 パッケージはこの制約を受けない。
試しに、ATS と usesCleartextTraffic を設定 (つまり非 HTTPS の強制遮断) し、非ネイティブ実装、ネイティブ実装 (といっても inter-op が考慮されており dart で扱える) で挙動を比べてみた。
下記のパッケージを比較している。
- dart:io (標準パッケージ)
- 非ネイティブ実装
- http (https://pub.dev/packages/http)
- 非ネイティブ実装
- cupertino_http (https://pub.dev/packages/cupertino_http)
- iOS のネイティブ実装
- cronet_http (https://pub.dev/packages/cronet_http)
- Android のネイティブ実装
この通り、非ネイティブ実装は ATS や usesCleartextTraffic の影響を一切受けていない。
flutter のバージョンの問題
確認はしていないが、flutter の過去のバージョンで、ATS や usesCleartextTraffic のように、OS 側で強制的に非 HTTPS 通信を遮断していた時期があった模様。
それが、Insecure HTTP connections are disabled by default on iOS and Android。
結局、このページ書かれているように Non-secure connection to local IP refused #72723 で議論され、この実装は元に戻された。
下の方には
- Landed in version: 1.23
- In stable release: 2.0.0
- Reverted in version: 2.2.0 (proposed)
とあり、Flutter 2.2.0 以降は、この問題は発生しないと思われる。
2.2.0 のリリースが Windows 版で 2021/5/19 なので、その辺りに書かれたブログなどで、HTTP の遮断についての話をしているなら、それはもう古い記事である。
これらとかね。
- FlutterでlocalhostのAPIサーバーに接続する
- [Flutter]「Insecure HTTP is not allowed by platform」の対処法
- Hydro-SDK で始める TypeScript を使った Flutter 開発
少なくとも、http パッケージや dart:io パッケージなら、 Bad state: Insecure HTTP is not allowed by platform
なんて表示されないのです。