使用 Firebase 遠程配置逐步推出 Firebase 應用檢查

透過集合功能整理內容 你可以依據偏好儲存及分類內容。

一、簡介

您可以使用Firebase App Check和 App Attest 來保護您的後端服務並驗證對 Firebase 服務的請求是否來自您的真實應用。

通常建議用戶逐步加入 App Attest 服務,以避免達到配額限制。有關詳細信息,請參閱 Apple 的“準備使用應用程序證明服務”文檔。

如“分階段發布版本更新”中所述,使用 Apple 的 App Store Connect 功能逐步發布應用更新的能力可以使 App Check 的推出更加順暢。這是一個簡單明了的解決方案。但是,分階段發布應用程序版本更新不允許您在不發布新應用程序版本的情況下控制現有更新應用程序的推出或更改行為。

通過 App Attest 部署對 App Check 進行更多控制的一種方法是使用 Firebase Remote Config 為您的應用程序的一定百分比的用戶啟用 App Check with App Attest。這可能有助於避免來自證明服務器的限制。谷歌分析可用於觀察推出對用戶的影響。

你會學到什麼

在這個多步驟代碼實驗室中,您將了解如何使用 Firebase 遠程配置為您的應用推出 App Check。

此代碼實驗室使用基於 DatabaseExample 快速入門應用並與 Firebase 應用檢查集成的 Firebase 項目,如Apple 平台的 Firebase 應用檢查代碼實驗室中所述。 DatabaseExample 快速入門應用允許用戶使用 Firebase 實時數據庫的功能登錄和添加帖子。

您還可以調整此代碼實驗室中的步驟來測試您自己的應用程序。

先決條件

你需要什麼

  • Xcode 12.5+
  • 對於 App Attest 測試:
    • 一個 Apple Developer 帳戶,可讓您創建新的應用標識符
    • 具有顯式 App ID 且啟用了 App Attest 功能的應用程序。如果您需要有關該過程的幫助,請參閱註冊應用 ID啟用應用功能文章。
    • 支持App Attest的 iOS/iPadOS 設備
  • Firebase 項目:
  • 訪問您應用的關聯 Firebase 項目,並有權創建和管理遠程配置以及查看 Google Analytics(分析)

2. 創建自定義證明提供者

在這一步中,我們將創建一個自定義提供程序類,以僅在啟用 App Attest 時提供令牌。遠程配置依賴於已配置的 Firebase 應用實例,您在此步驟中實現的自定義提供程序充當佔位符以完成配置。

要完成以下步驟,您需要在 Xcode 中應用的Frameworks、Libraries 和 Embedded Content 部分添加FirebaseFirebaseRemoteConfigFirebaseAnalytics 。有關如何執行此操作的示例,請參閱Apple 平台的 Firebase 應用檢查代碼實驗室

  1. 創建一個文件“ MyAppCheckProvider ”,它是符合AppCheckProvider協議的NSObject的子類。
  2. 包括一個稍後將填寫的空getToken()方法。

有關具有空getToken()方法的自定義提供程序類,請參見以下示例代碼。

// MyAppCheckProvider.swift

import Firebase
import FirebaseAnalytics
import FirebaseAppCheck
import FirebaseRemoteConfig

class MyAppCheckProvider: NSObject, AppCheckProvider {
  func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) {}
}

要實例化AppAttestProvider ,您需要傳遞相應FirebaseApp的實例。為其創建一個存儲屬性並將其作為初始值設定項參數接受:

// MyAppCheckProvider.swift

import Firebase
import FirebaseAnalytics
import FirebaseAppCheck
import FirebaseRemoteConfig

class MyAppCheckProvider: NSObject, AppCheckProvider {
  // Firebase app instance served by the provider.
  let firebaseApp: FirebaseApp

  // The App Check provider factory should pass the FirebaseApp instance.
  init(app: FirebaseApp) {
    self.firebaseApp = app
    super.init()
  }

  func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) {}
}

將令牌請求轉發給 App Attest 提供者

現在,您可以在 getToken getToken()方法中將令牌請求轉發給 App Attest 提供程序。

注意:在FirebaseAppCheck 框架參考中了解有關getToken()方法的更多信息。

將以下代碼添加到您的getToken()方法中:

// MyAppCheckProvider.swift

import Firebase
import FirebaseAnalytics
import FirebaseAppCheck
import FirebaseRemoteConfig

class MyAppCheckProvider: NSObject, AppCheckProvider {
  // Firebase app instance served by the provider.
  let firebaseApp: FirebaseApp

  // The App Check provider factory should pass the FirebaseApp instance.
  init(app: FirebaseApp) {
    self.firebaseApp = app
    super.init()
  }

  private lazy var appAttestProvider = AppAttestProvider(app: firebaseApp)

  func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) {
    // Fetch App Attest flag from Remote Config
    let remoteConfig = RemoteConfig.remoteConfig(app: firebaseApp)
    remoteConfig.fetchAndActivate { remoteConfigStatus, error in
      // Get App Attest flag value
      let appAttestEnabled = remoteConfig.configValue(forKey: "AppAttestEnabled").boolValue

      guard appAttestEnabled else {
        // Skip attestation if App Attest is disabled. Another attestation
        // method like DeviceCheck may be used instead of just skipping.
        handler(nil, MyProviderError.appAttestIsDisabled)
        return
      }

      // Try to obtain an App Attest provider instance and fail if cannot
      guard let appAttestProvider = self.appAttestProvider else {
        handler(nil, MyProviderError.appAttestIsUnavailable)
        return
      }

      // If App Attest is enabled for the app instance, then forward the
      // Firebase App Check token request to the App Attest provider
      appAttestProvider.getToken(completion: handler)
    }
  }
}

enum MyProviderError: Error {
  case appAttestIsDisabled
  case appAttestIsUnavailable
  case unexpected(code: Int)
}

前面的代碼檢查了一個 Remote Config AppAttestEnabled布爾參數(這個 Remote Config 參數將在後面的代碼實驗室中創建)。如果值為false,則代碼失敗,表明當前設備上沒有推出App Check。如果該值為 true,則代碼會嘗試獲取 App Attest 提供程序,如果無法獲取則失敗。如果這些錯誤檢查通過,代碼會將令牌請求轉發給 App Attest 提供者。

添加分析事件

通過添加 Analytics 事件,您可以更好地了解 App Check 推出的成功程度。分析將幫助確定是否應該為更多的受眾啟用 App Attest。

記錄兩個 Analytics 事件:成功時AppAttestSuccess和失敗時AppAttestFailure 。這兩個分析事件可以幫助跟踪您的應用檢查推出的成功,並幫助您決定是否應該繼續進行更大規模的推出。

func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) {
  // Fetch Remote Config.
  let remoteConfig = RemoteConfig.remoteConfig(app: firebaseApp)
  remoteConfig.fetchAndActivate { remoteConfigStatus, error in
    // Get App Attest flag value from Remote Config.
    let appAttestEnabled = remoteConfig.configValue(forKey: "AppAttestEnabled").boolValue

    guard appAttestEnabled else {
      // Skip attestation if App Attest is disabled. Another attestation
      // method like DeviceCheck may be used instead of just skipping.
      handler(nil, MyProviderError.appAttestIsDisabled)
      return
    }

    // Try to obtain an App Attest provider instance and fail otherwise.
    guard let appAttestProvider = self.appAttestProvider else {
      handler(nil, MyProviderError.appAttestIsUnavailable)
      return
    }

    // If App Attest is enabled for the app instance, then forward the
    // Firebase App Check token request to the App Attest provider.
    appAttestProvider.getToken { token, error in
      // Log an Analytics event to track attestation success rate.
      let appAttestEvent: String
      if (token != nil && error == nil) {
        appAttestEvent = "AppAttestSuccess"
      } else {
        appAttestEvent = "AppAttestFailure"
      }
      Analytics.logEvent(appAttestEvent, parameters: nil)

      // Pass the result to the handler
      handler(token, error)
    }
  }
}

3.更新提供者工廠類

在您實現了將令牌請求轉發到 App Attest 提供者的邏輯並添加了一些分析事件之後,您需要更新您在App Check for Apple Platforms MyAppCheckProviderFactory.class中創建的 MyAppCheckProviderFactory.class。此類將針對模擬器的App Check 調試提供程序,否則將針對您的自定義提供程序。

在您在Firebase App Check for Apple 平台代碼實驗室中創建的MyAppCheckProviderFactory類中編輯以下代碼:

// MyAppCheckProviderFactory.swift

import Firebase

class MyAppCheckProviderFactory: NSObject, AppCheckProviderFactory {
  func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
      #if targetEnvironment(simulator)
      // App Attest is not available on simulators.
      // Use a debug provider.
      let provider = AppCheckDebugProvider(app: app)

      // Print only locally generated token to avoid a valid token leak on CI.
      print("Firebase App Check debug token: \(provider?.localDebugToken() ?? "" )")

      return provider
      #else
      if #available(iOS 14.0, *) {
        // Use your custom App Attest provider on real devices.
        return MyAppCheckProvider(app: app)
      } else {
        return DeviceCheckProvider(app: app)
      }
      #endif
  }
}

在配置FirebaseApp之前確認您已設置AppCheckProviderFactory

// DatabaseExampleApp.swift

import SwiftUI
import Firebase
import FirebaseAppCheck

@main
struct DatabaseExampleApp: App {
  init() {
    AppCheck.setAppCheckProviderFactory(MyAppCheckProviderFactory())
    FirebaseApp.configure()
  }

  // ...
}

4.在Firebase控制台中添加Remote Config參數

您現在將遠程配置參數AppAttestEnabled添加到 Firebase 控制台。您的getToken方法需要此參數。

要在 Firebase 控制台中創建遠程配置參數:

  1. 為您的項目打開遠程配置,然後單擊添加參數。如果這是您第一次使用遠程配置,請單擊創建配置
  2. 參數名稱(鍵)字段中,輸入AppAttestEnabled
  3. 數據類型下拉列表中,選擇布爾值
  4. 默認值下拉列表中,選擇false

在 Firebase 控制台中創建遠程配置參數

在單擊保存之前,為 10% 的用戶創建一個條件值:

  1. 單擊添加新>條件值>創建新條件
  2. 名稱字段中,輸入條件名稱。
  3. Apply if...下,選擇User in random percentile , <= ,然後在%字段中輸入10
  4. 單擊創建條件

在 Firebase 控制台中定義遠程配置條件

將條件值設置為true ,以便 App Attest 向 10% 的用戶推出。

  1. 將您剛剛創建的條件的值設置為true
  2. 單擊保存

在 Firebase 控制台中查看遠程配置參數

完成後,發布遠程配置更改。

在您的設備上測試部署

要在不修改應用代碼的情況下在您的設備上測試不同的遠程配置標誌值,請按照使用 A/B 測試創建 Firebase 遠程配置實驗教程AppAttestEnabled參數上配置一個實驗。教程部分“在測試設備上驗證您的實驗”解釋瞭如何為您的測試設備分配不同的值。

最後一步是使用 Google Analytics 來監控您的 App Attest 推出是否成功。

5. 回顧您的 AppCheck 推出是否成功

您可以在 Analytics Events 儀表板上衡量您的部署是否成功。注意AppAttestSuccessAppAttestFailure事件。最多可能需要 24 小時才能在儀表板中看到事件。或者,您可以啟用調試並使用 DebugView 更快地查看調試事件。

或者,您可以監控 Crashlytics 儀表板以了解崩潰率的增加。如需詳細了解如何將 Crashlytics 添加到您的應用,請參閱Firebase Crashlytics 入門

一旦您看到大部分AppAttestSuccess事件和少數AppAttestFailure事件,這是一個很好的跡象,您可以通過修改 Remote Config 參數AppAttestEnabled中的條件來增加啟用 App Attest 的用戶百分比。

在 Firebase 控制台中查看 Analytics 事件

可選:利用 Google Analytics Audience

如果您想進一步利用AppAttestEnabled Analytics 事件,您可以創建一個Analytics Audience來跟踪AppAttestEnabled設置為 true 的用戶。

App Attest 隨 iOS 14.0 一起發布。您的某些用戶可能不在此版本中,因此沒有資格獲得 App Attest。您可以記錄另一個 Analytics 事件以跟踪這些用戶,然後針對該受眾群體使用另一種證明方法,例如DeviceCheck

可選:使用 Crashlytics 監控崩潰

為了更好地了解您的應用在推出期間的穩定性,請使用Firebase Crashlytics監控崩潰和非致命事件。

6. 恭喜!

您成功推出了帶有遠程配置的 App Check 🎉

其他資源: