1. 简介
您可以将 Firebase App Check 与 App Attest 搭配使用,以保护后端服务并验证发送到 Firebase 服务的请求是否来自真实的应用。
一般建议您逐步将用户加入 App Attest 服务,以免达到配额限制。如需了解详情,请参阅 Apple 的“准备使用 App Attest 服务”文档。
如“分阶段发布版本更新”中所述,使用 Apple 的 App Store Connect 功能逐步发布应用更新,可以使 App Check 的发布更加顺畅。这是一个简单明了的解决方案。不过,分阶段发布应用版本更新无法让您在不发布新应用版本的情况下控制现有已更新应用的发布或更改其行为。
如需更好地控制 App Check 与 App Attest 的推出,一种方法是使用 Firebase Remote Config 每次为应用的部分用户启用 App Check 与 App Attest。这有助于避免证明服务器进行节流。您可以使用 Google Analytics 来观察发布对用户的影响。
学习内容
在此 Codelab 中,您将学习如何使用 Firebase 远程配置为您的应用推出 App Check。
此 Codelab 使用基于 DatabaseExample 快速入门应用的 Firebase 项目,并与 Firebase App Check 集成,如 Firebase App Check for Apple Platforms Codelab 中所述。DatabaseExample 快速入门应用允许用户使用 Firebase Realtime Database 的功能登录并添加帖子。
您还可以调整此 Codelab 中的步骤,以测试自己的应用。
前提条件
所需条件
- Xcode 12.5+
- 对于 App Attest 测试:
- 一个 Apple Developer 账号,可用于创建新的应用标识符
- 已启用 App Attest 功能且具有明确应用 ID 的应用。如果您在完成此流程时需要帮助,请参阅注册应用 ID 和启用应用功能这两篇文章。
- 支持 App Attest 的 iOS/iPadOS 设备
- 具有以下特征的 Firebase 项目:
- 已配置的 iOS 应用(了解详情)
- Google Analytics、Remote Config 和 App Check 已启用
- 有权访问您应用的关联 Firebase 项目,并且有权使用和管理 Remote Config 以及查看 Google Analytics
2. 创建自定义证明提供程序
在此步骤中,我们将创建一个自定义提供程序类,以便仅在启用 App Attest 时提供令牌。Remote Config 依赖于已配置的 Firebase 应用实例,而您在此步骤中实现的自定义提供程序充当占位符以完成配置。
如需完成以下步骤,您需要在 Xcode 中应用的“框架、库和嵌入式内容”部分添加 Firebase
、FirebaseRemoteConfig
和 FirebaseAnalytics
。如需查看相关示例,请参阅 Firebase App Check for Apple platforms Codelab。
- 创建一个名为“MyAppCheckProvider”的文件,该文件是
NSObject
的子类,符合AppCheckProvider
协议。 - 添加一个空的
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()
方法中将令牌请求转发给 App Attest 提供方的所有条件。
注意:如需详细了解 getToken()
方法,请参阅 FirebaseAppCheck 框架参考。
将以下代码添加到您的 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 参数将在本 Codelab 的后续步骤中创建)。如果值为 false,则代码会失败,表明当前设备上未推出应用检查。如果值为 true,则代码会尝试获取 App Attest 提供程序,如果无法获取,则会失败。如果通过了这些错误检查,代码会将令牌请求转发给应用密钥提供方。
添加 Google Analytics 事件
通过添加 Analytics 事件,您可以更深入地了解 App Check 发布是否成功。Analytics 将帮助您确定是否应为更多受众群体启用 App Attest。
成功时记录 AppAttestSuccess Analytics 事件,失败时记录 AppAttestFailure Analytics 事件。这两个 Google 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. 更新提供方工厂类
在实现将令牌请求转发给 App Attest 提供方的逻辑并添加一些 Google Analytics 事件后,您需要更新在 针对 Apple 平台的 App Check 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 控制台中添加 Remote Config 参数
现在,您将向 Firebase 控制台添加 Remote Config 参数 AppAttestEnabled。您的 getToken
方法需要此参数。
如需在 Firebase 控制台中创建 Remote Config 参数,请执行以下操作:
- 打开项目的 Remote Config,然后点击添加参数。如果您是首次使用 Remote Config,请点击创建配置。
- 在参数名称(键)字段中,输入
AppAttestEnabled
。 - 从数据类型下拉菜单中,选择布尔值。
- 从默认值下拉菜单中,选择 false。
在点击“保存”之前,请为 10% 的用户创建条件值:
- 依次点击添加新 > 条件值 > 创建新条件。
- 在名称字段中,输入条件名称。
- 在应用条件下,依次选择用户位于随机百分位、<=,然后在%字段中输入 10。
- 点击创建条件。
将条件值设置为 true,以便向 10% 的用户推出应用密钥。
- 将您刚刚创建的条件的值设置为 true。
- 点击保存。
完成后,发布 Remote Config 更改。
在设备上测试发布
如需在设备上测试不同的 Remote Config 标志值,而无需修改应用代码,请按照使用 A/B Testing 创建 Firebase Remote Config 实验教程中的说明,针对 AppAttestEnabled 参数配置实验。教程部分“在测试设备上验证您的实验”介绍了如何为测试设备分配不同的值。
最后一步是使用 Google Analytics 监控应用证明发布情况的成效。
5. 查看 AppCheck 发布作业的成功情况
您可以在“Analytics 事件”信息中心内衡量发布效果。留意 AppAttestSuccess 和 AppAttestFailure 事件。您最长可能需要等待 24 小时才能在信息中心内看到事件。或者,您也可以启用调试功能,并使用 DebugView 更快速地查看调试事件。
您还可以选择监控 Crashlytics 信息中心,查看崩溃率是否有所增加。如需详细了解如何将 Crashlytics 添加到应用中,请参阅 Firebase Crashlytics 使用入门。
如果您看到的大多是 AppAttestSuccess 事件,而 AppAttestFailure 事件很少,则表明您可以修改 Remote Config 参数 AppAttestEnabled 中的条件,以增加启用 App Attest 的用户百分比。
可选:利用 Google Analytics 受众群体
如果您想进一步利用 AppAttestEnabled Analytics 事件,可以创建一个 Analytics 受众群体来跟踪将 AppAttestEnabled 设置为 true 的用户。
App Attest 随 iOS 14.0 一起发布。您的部分用户可能未使用此版本,因此不符合应用密钥证明的条件。您可以记录另一个 Google Analytics 事件来跟踪这些用户,然后针对该受众群体采用其他证明方法,例如 DeviceCheck。
可选:使用 Crashlytics 监控崩溃情况
为了更好地了解应用在发布期间的稳定性,请使用 Firebase Crashlytics 监控崩溃和非严重错误。
6. 恭喜!
您已成功通过 Remote Config 推出 App Check 🎉