okaryo.log

FlutterアプリでAndroid/iOSの自動バックアップを無効化する | okaryo.log

FlutterアプリでAndroid/iOSの自動バックアップを無効化する

    #Flutter#セキュリティ

自動バックアップとは

Android/iOSにはアプリのデータをGoogleドライブやiCloudに自動でバックアップする機能があります(バージョンや端末によりますが)。そうすることで、端末を変えた際にスムーズに以前の端末のアプリを使い続けることができ、ユーザビリティが向上します。したがって、基本的に自動バックアップは有効にした方が良いかと思います。

しかし、自動バックアップされるデータに認証情報等が含まれている場合、セキュリティ脆弱性につながる可能性があります。基本的にアプリのデータに個人情報や認証情報は保存すべきではありませんが、APIへのアクセストークンを一時的に保存したり、FirebaseAuthenticationといったライブラリによってトークンを保存する場面もあるかと思います。

機密情報を扱っていたり、アプリの特性や要件として上記のようなトークンであっても自動バックアップしたくないといったこともあるかと思います。本記事では、Android/iOSにおけるFlutter開発で自動バックアップを無効にする方法を紹介します。

Androidでの自動バックアップ無効

AndroidManifestでandroid:allowBackup="false"の指定をします。

<manifest ... >
    ...
    <application android:allowBackup="false" ... >
        ...
    </application>
</manifest>

公式ドキュメントはこちらになります。Android12以上をターゲットにしている場合は別の対応が必要になります。 https://developer.android.com/guide/topics/data/autobackup?hl=ja#EnablingAutoBackup

iOSでの自動バックアップ無効

以下の公式ドキュメントを参考に設定しました。 https://developer.apple.com/documentation/foundation/optimizing_app_data_for_icloud_backup

ドキュメントによると、iOSでのアプリのデータはDocuments, Libraryディレクトリに保存されます。そこで、これらのディレクトリをバックアップ対象外とする処理をSwiftで書き、FlutterのMethodChannelを使ってその処理を呼び出すという風にしました。

Swiftのコードは以下です。公式ドキュメントにあったコード片も参考にしましたが、Swiftに全然詳しくないので書き方などなっていない箇所があるかと思います。

// ios/Runner/AppDelegate.swift
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
        let methodChannel = FlutterMethodChannel(name: "com.example.okaryo/disable_iCloud_backup", binaryMessenger: controller.binaryMessenger)

        methodChannel.setMethodCallHandler({
            [weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
            guard call.method == "disable_iCloud_backup" else {
                result(FlutterMethodNotImplemented)
                return
            }
            self?.disableICloudBackup(result: result)
        })

        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    private func disableICloudBackup(result: FlutterResult) {
        do {
            try setExcludeFromICloudBackup(filePath: NSHomeDirectory() + "/Library")
            try setExcludeFromICloudBackup(filePath: NSHomeDirectory() + "/Documents")
            result(nil)
        } catch {
            exit(0)
        }
    }

    private func setExcludeFromICloudBackup(filePath: String) throws {
        let url = NSURL.fileURL(withPath: filePath) as NSURL
        try url.setResourceValue(true, forKey: URLResourceKey.isExcludedFromBackupKey)
    }
}

Flutter側ではこれをmain関数内でMethodChannelを使って呼び出します。

// lib/main.dart
main() async {
  await _disableICloudBackup();

  runApp(App());
}

_disableICloudBackup() async {
  if (Platform.isIOS) {
    const channel = MethodChannel('com.example.okaryo/disable_iCloud_backup');
    await channel.invokeMethod('disable_iCloud_backup');
  }
}

おわり

繰り返しになりますが、自動バックアップ設定はユーザビリティためのに基本的に有効にしておくべきだと思います。無効にする際は、アプリの要件等を踏まえてよく検討してからにしてください。


関連記事
最新記事
プロモーション

This site uses Google Analytics.