使用 Firebase Remote Config 逐步推出 Firebase App Check

一、简介

您可以将Firebase App Check与 App Attest 结合使用来保护您的后端服务并验证对 Firebase 服务的请求是否来自您的真实应用。

通常建议用户逐步加入应用程序证明服务,以避免达到配额限制。有关更多信息,请参阅 Apple 的“准备使用应用程序证明服务”文档。

使用 Apple 的 App Store Connect 功能增量发布应用程序更新的能力(如“分阶段发布版本更新”中所述)可以使 App Check 的推出更加顺利。这是一个直接、简单的解决方案。但是,分阶段发布应用程序版本更新不允许您在不发布新应用程序版本的情况下控制现有更新应用程序的推出或更改行为。

对带有应用程序证明的应用程序检查推出进行更多控制的一种方法是使用 Firebase 远程配置一次为一定比例的应用用户启用带有应用程序证明的应用程序检查。这可能有助于避免来自证明服务器的限制。 Google Analytics 可用于观察此次推出对用户的影响。

你将学到什么

在此多步骤 Codelab 中,您将了解如何使用 Firebase Remote Config 为您的应用推出 App Check。

此 Codelab 使用基于 DatabaseExample 快速入门应用并与 Firebase App Check 集成的 Firebase 项目,如适用于 Apple 平台的 Firebase App Check 代码实验室中所述。 DatabaseExample 快速入门应用允许用户使用 Firebase 实时数据库的功能登录并添加帖子。

您还可以调整此 Codelab 中的步骤来测试您自己的应用。

先决条件

你需要什么

  • Xcode 12.5+
  • 对于应用程序证明测试:
    • 允许您创建新应用程序标识符的 Apple 开发者帐户
    • 具有显式 App ID 且启用了 App Attest 功能的应用程序。如果您需要有关该过程的帮助,请参阅注册应用程序 ID启用应用程序功能文章。
    • 支持App Attest的iOS/iPadOS设备
  • Firebase 项目包含:
  • 访问您应用的关联 Firebase 项目,并有权创建和管理远程配置以及查看 Google Analytics(分析)

2. 创建自定义证明提供者

在此步骤中,我们将创建一个自定义提供程序类,以便仅在启用应用程序证明时提供令牌。远程配置依赖于已配置的 Firebase 应用实例,您在此步骤中实现的自定义提供程序充当占位符来完成配置。

要完成以下步骤,您需要在 Xcode 中应用的框架、库和嵌入式内容部分中添加FirebaseFirebaseRemoteConfigFirebaseAnalytics 。有关如何执行此操作的示例,请参阅适用于 Apple 平台的 Firebase 应用程序检查 Codelab

  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) {}
}

将令牌请求转发给应用程序证明提供商

现在,您已拥有将令牌请求转发到getToken()方法中的应用程序证明提供程序的一切。

注意:在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)
}

前面的代码检查远程配置AppAttestEnabled布尔参数(此远程配置参数将在稍后的 Codelab 中创建)。如果值为 false,则代码失败,表明当前设备上尚未推出 App Check。如果该值为 true,则代码会尝试获取 App Attest 提供程序,如果无法获取则会失败。如果这些错误检查通过,代码会将令牌请求转发给 App Attest 提供商。

添加分析事件

通过添加分析事件,您可以更好地了解应用程序检查部署的成功程度。分析将帮助确定是否应该为更多受众启用应用程序证明。

记录两个 Analytics 事件:成功时记录AppAttestSuccess ,失败时记录AppAttestFailure 。这两个 Analytics 事件可以帮助跟踪 App Check 部署的成功情况,并帮助您决定是否应该继续进行更大规模的部署。

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.更新ProviderFactory类

实现将令牌请求转发到 App Attest 提供程序的逻辑并添加一些 Analytics 事件后,您需要更新在App Check for Apple Platforms Codelab中创建的MyAppCheckProviderFactory.class 。此类将以模拟器的App Check 调试提供程序为目标,否则以您的自定义提供程序为目标。

在您在适用于 Apple 平台的 Firebase App Check Codelab中创建的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 控制台中添加远程配置参数

您现在将远程配置参数AppAttestEnabled添加到 Firebase 控制台。您的getToken方法需要此参数。

要在 Firebase 控制台中创建远程配置参数:

  1. 打开您的项目的远程配置并单击添加参数。如果这是您第一次使用远程配置,请单击创建配置
  2. 参数名称(键)字段中,输入AppAttestEnabled
  3. 数据类型下拉列表中,选择布尔值
  4. 默认值下拉列表中,选择false

在 Firebase 控制台中创建远程配置参数

在单击“保存”之前,为 10% 的用户创建条件值:

  1. 单击新增>条件值>创建新条件
  2. 名称字段中,输入条件名称。
  3. “应用如果...”下,选择“随机百分位数中的用户”“<= ”,然后在“ %”字段中输入10
  4. 单击创建条件

在 Firebase 控制台中定义远程配置条件

将条件值设置为true ,以便应用程序证明将推广到 10% 的用户。

  1. 将刚刚创建的条件的值设置为true
  2. 单击“保存”

在 Firebase 控制台中查看远程配置参数

完成后,发布远程配置更改。

在您的设备上测试部署

要在不修改应用代码的情况下测试设备上的不同远程配置标志值,请按照使用 A/B 测试创建 Firebase 远程配置实验教程,AppAttestEnabled参数上配置实验。教程部分“在测试设备上验证您的实验”解释了如何为您的测试设备分配不同的值。

最后一步是使用 Google Analytics 来监控应用程序证明部署是否成功。

5. 检查 AppCheck 部署是否成功

您可以在 Analytics Events 仪表板上衡量部署是否成功。监视AppAttestSuccessAppAttestFailure事件。最多可能需要 24 小时才能在仪表板中查看事件。或者,您可以启用调试并使用 DebugView 更快地查看调试事件。

或者,您可以监控 Crashlytics 仪表板以了解崩溃率的增加情况。有关将 Crashlytics 添加到您的应用的更多信息,请参阅Firebase Crashlytics 入门

一旦您看到大部分AppAttestSuccess事件和少量AppAttestFailure事件,这是一个好兆头,表明您可以通过修改远程配置参数AppAttestEnabled中的条件来增加启用 App Attest 的用户百分比。

在 Firebase 控制台中查看 Analytics 事件

可选:利用 Google Analytics 受众

如果您想进一步利用AppAttestEnabled Analytics 事件,您可以创建一个Analytics Audience来跟踪将AppAttestEnabled设置为 true 的用户。

App Attest 随 iOS 14.0 一起发布。您的某些用户可能未使用此版本,因此没有资格进行应用程序证明。您可以记录另一个 Analytics 事件来跟踪这些用户,然后针对该受众群体使用另一种证明方法,例如DeviceCheck

可选:使用 Crashlytics 监控崩溃

为了更好地了解应用在推出期间的稳定性,请使用Firebase Crashlytics来监控崩溃和非致命事件。

6. 恭喜!

您已成功推出带有远程配置的 App Check 🎉

其他资源: