保護您的Flutter應用程式:實現隱私螢幕

發表於2023-09-19

在當今技術驅動的世界中,隱私是應用程式開發人員最關心的問題。無論是敏感的個人資訊、安全的交易細節,還是機密的企業資料,應用程式通常都會處理一些應防止被窺探的資料。

一個經常被忽視的隱私問題是任務切換器中顯示的或觸發截圖時拍攝的應用程式快照。無意中暴露這些快照中的敏感資料會導致嚴重後果。

作為 Flutter 開發人員,我們有能力透過實施一項簡單而有效的功能——“隱私螢幕”,將這些風險降至最低。

什麼是隱私螢幕?

隱私螢幕又稱安全螢幕或應用遮蔽,本質上是一個保護層,當應用處於後臺或呼叫任務切換器時,它將覆蓋應用的可見介面。該保護層可防止未經授權的使用者有意或無意地檢視敏感資訊,從而增加了一層額外的安全保護。

為什麼隱私螢幕很重要?

雖然 Android 和 iOS 等作業系統提供了管理應用程式生命週期的固有機制,但管理應用程式的資料和狀態仍是開發人員的責任。在處理敏感資料時,這一點變得至關重要。

例如,銀行應用程式可能會顯示賬戶詳情、交易歷史或其他敏感資料。如果使用者在未登出的情況下切換到另一個應用程式,這些資料就可能在應用程式切換器中被看到。實施隱私螢幕可以在不使用應用程式時隱藏這些資料,從而降低此類風險。

何時使用隱私螢幕?

你應該考慮為以下應用設定隱私螢幕:

  1. 處理敏感的使用者資料,如財務資訊、個人健康資料或專有業務資料。
  2. 可能在共用或公共環境中使用,因為在這種環境中,越肩窺探可能是一種風險。

在 Flutter 中實現隱私螢幕

在flutter中,隱私螢幕的實現涉及特定於平臺的程式碼,因為Android和iOS的過程有所不同。

For android

Android 提供了一種內建機制,透過使用 WindowManager.LayoutParams.FLAG_SECURE 來確保螢幕內容的安全。該標記將視窗內容視為安全內容,止其出現在螢幕截圖中或在非安全螢幕上被檢視。

在我們的 flutter 應用程式中,我們可以透過編寫一些 Kotlin 程式碼來利用這一功能,以便在需要時啟用或禁用它。

讓我們深入瞭解程式碼:

MainActivity.kt

import android.app.Activity
import android.content.Intent
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import android.view.WindowManager

class MainActivity: FlutterActivity() {
    private val CHANNEL = "security"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        setupMethodChannel(flutterEngine)
    }

    private fun setupMethodChannel(flutterEngine: FlutterEngine) {
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            when (call.method) {
                "enableAppSecurity" -> {
                    enableAppSecurity()
                    result.success(null)
                }
                "disableAppSecurity" -> {
                    disableAppSecurity()
                    result.success(null)
                }
                else -> result.notImplemented()
            }
        }
    }

    override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)
        toggleAppSecurity(hasFocus)
    }

    override fun onPause() {
        super.onPause()
        enableAppSecurity()
    }

    override fun onResume() {
        super.onResume()
        disableAppSecurity()
    }

    private fun toggleAppSecurity(hasFocus: Boolean) {
        if (hasFocus) {
            disableAppSecurity()
        } else {
            enableAppSecurity()
        }
    }

    private fun enableAppSecurity() {
        window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
    }

    private fun disableAppSecurity() {
        window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
    }
}

MainActivity 繼承自 FlutterActivity,我們過載 configureFlutterEngine 函式來設定方法通道。該方法通道允許 Flutter 和 Android 之間進行通訊。我們正在監聽 Flutter 的兩個方法 enableAppSecuritydisableAppSecurity,以切換安全標記。

toggleAppSecurity 函式會檢查應用程式是否有視窗焦點。如果有焦點,我們就會禁用安全標記,否則就會啟用。我們還在 onPause 函式中呼叫 enableAppSecurity,在 onResume 函式中呼叫 disableAppSecurity。這樣可以確保應用程式不在前臺時,應用程式內容是安全的,而當應用程式進入前臺時,應用程式內容又是可見的。

透過實現這一點,當我們的應用程式的螢幕內容不在前臺時,它將得到保護,增強我們的應用程式的隱私和保護敏感資料。

For iOS

與 Android 一樣,iOS 也允許我們使用模糊效果來保護應用螢幕的隱私。不過,由於 iOS 和 Android 平臺的不同,使用方法也略有不同。

讓我們來分析一下 iOS 的實現:

AppDelegate.swift

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  private var flutterViewController: FlutterViewController!
  private var securityChannel: FlutterMethodChannel!
  private var blurEffectView: UIVisualEffectView?
  private var isInBackground: Bool = false // Track whether app is in background
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)

    setupFlutterCommunication()

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  private func setupFlutterCommunication() {
    flutterViewController = window?.rootViewController as? FlutterViewController
    securityChannel = FlutterMethodChannel(
      name: "security",
      binaryMessenger: flutterViewController.binaryMessenger
    )

    securityChannel.setMethodCallHandler(handle)
  }

  override func applicationDidEnterBackground(_ application: UIApplication) {
    isInBackground = true // App entered background
    enableAppSecurity()
  }

  override func applicationDidBecomeActive(_ application: UIApplication) {
    // Check if the app was in background before becoming active
    if isInBackground {
      disableAppSecurity()
      isInBackground = false
    }
  }

  private func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
    switch call.method {
    case "enableAppSecurity":
      result(nil)
    case "disableAppSecurity":
      result(nil)
    default:
      result(FlutterMethodNotImplemented)
    }
  }

  private func enableAppSecurity() {
    let blurEffect = UIBlurEffect(style: .light)
    blurEffectView = UIVisualEffectView(effect: blurEffect)
    blurEffectView?.frame = window!.frame
    window?.addSubview(blurEffectView!)
  }

  private func disableAppSecurity() {
    blurEffectView?.removeFromSuperview()
  }
}

我們使用 UIApplicationMain 來表示 iOS 應用程式的入口點。這類似於 C 或 C++ 程式中的 main() 函式。AppDelegate 類繼承自 FlutterAppDelegate,它允許我們訪問應用程式生命週期回撥和主 UIWindow

application(_:didFinishLaunchingWithOptions:) 方法中,我們初始化了 FlutterMethodChannel,以便與 Flutter 通訊。我們使用 setMethodCallHanlder(_:) 來處理 Flutter 方法呼叫。

當應用程式進入後臺時,我們會設定 isInBackground 標誌並啟用安全功能。這將在 applicationDidEnterBackground(_:) 方法中完成。

另一方面,當應用程式開始執行時,我們會檢查它在開始執行前是否在後臺。如果是,我們將禁用應用程式的安全性,並重置 isInBackground 標誌。

enableAppSecurity() 函式可建立模糊效果並將其應用到 UIVisualEffectView 中,然後將其新增到視窗中。當從應用程式切換器或螢幕截圖檢視應用程式時,這將有效地模糊應用程式的使用者介面。

disableAppSecurity() 函式只是從視窗中移除 UIVisualEffectView,從而顯示應用程式的使用者介面。

透過採用這種方法,我們可以確保應用程式的使用者介面在不使用時受到保護,從而提高使用者資料的私密性,並遵守應用程式安全的最佳實踐。

Flutter整合

對於使用跨平臺框架 Flutter 開發的應用程式,MethodChannels 可用於與原生 Android 和 iOS 功能進行互動。

讓我們看看如何使用 Flutter 與我們在原生程式碼中定義的螢幕隱私功能進行互動:

platform_channel_util.dart

abstract class IAppScreenPrivacy {
  Future<void> enableScreenPrivacy();
  Future<void> disableScreenPrivacy();
}

class AppScreenPrivacyService extends IAppScreenPrivacy {
  static const platform = MethodChannel('security');
  @override
  Future<void> disableScreenPrivacy() async {
    try {
      await platform.invokeMethod('disableAppSecurity');
    } on PlatformException catch (e) {
      log('Failed to disable app security: "${e.message}"');
    }
  }

  @override
  Future<void> enableScreenPrivacy() async {
    try {
      await platform.invokeMethod('enableAppSecurity');
    } on PlatformException catch (e) {
      log('Failed to enable app security: "${e.message}"');
    }
  }
}

我們首先定義一個抽象類 IAppScreenPrivacy,該類有兩個方法:enableScreenPrivacy()disableScreenPrivacy()。擴充套件了 IAppScreenPrivacyAppScreenPrivacyService 類實現了這些方法。

每個方法都會嘗試呼叫原生程式碼中的相應函式。為此,我們使用了 MethodChannel 類的 invokeMethod 函式,並將希望呼叫的方法名稱作為引數傳遞。這些名稱必須與原生程式碼中定義的名稱一致,因此我們使用了 enableAppSecuritydisableAppSecurity

如果函式呼叫成功,螢幕隱私設定將被應用。但是,如果出現問題,invokeMethod 呼叫將丟擲 PlatformException 異常。該異常會被捕獲並記錄下來,以便除錯。

透過使用這個設定,我們可以直接從我們的Flutter程式碼中控制我們的原生應用安全功能。這使我們能夠利用本地開發的控制和力量,同時仍然受益於Flutter提供的生產力和易用性。

透過將這些安全實踐整合到我們的應用程式中,我們可以更好地保護使用者的敏感資訊,避免透過應用程式切換器或螢幕截圖不經意地暴露出來,從而確保增強使用者的隱私保護。

總結

透過在 Flutter 應用程式中新增隱私螢幕,您就邁出了增強應用程式隱私和安全性的重要一步。雖然這種技術不能確保您的應用程式免受所有型別的威脅,但它在保護使用者免受隨意窺探方面發揮著至關重要的作用。請記住,在現代應用程式開發中,謹慎處理敏感資料並遵守最佳安全規範不是一種選擇,而是一種必要。

請注意:本文僅為一般指南,根據您應用程式的具體需求,您可能需要使用更復雜的方法來保護敏感資料。請始終牢記遵守您所在地區與資料隱私相關的必要法律法規。


原文:https://articles.wesionary.team/securing-your-flutter-app-imp...

相關文章