适用于 Apple 平台的 Firebase App Check

1. 简介

Firebase App Check 可确保请求来自正当的应用和设备,从而有助于保护您的后端资源免遭滥用,例如防范账单欺诈和钓鱼式攻击。它可与 Firebase 服务以及您自己的后端服务搭配使用,以确保您的资源安全无虞。

如需详细了解 Firebase App Check,请参阅 Firebase 文档。

App Check 使用平台专有的服务来验证应用和/或设备的完整性。这些服务称为证明提供方。其中一个提供方是 Apple 的 App Attest 服务,App Check 可以使用该服务来验证 Apple 应用和设备的真实性。

构建内容

在此 Codelab 中,您将在现有示例应用中添加并强制执行 App Check,以便保护项目的 Realtime Database 免遭非法应用和设备的访问。

学习内容

  • 如何向现有应用添加 Firebase App Check。
  • 如何安装不同的 Firebase App Check 证明提供方。
  • 如何为应用配置 App Attest。
  • 如何在应用开发期间配置调试证明提供程序,以便在模拟器上测试应用。

所需条件

  • Xcode 13.3.1 或更高版本
  • 一个 Apple Developer 账号,可用于创建新的应用标识符
  • 支持 App Attest 的 iOS/iPadOS 设备(了解 App Attest API 的可用性

2. 获取初始项目

适用于 iOS 的 Firebase 快速入门代码库包含用于演示不同 Firebase 产品的示例应用。您将使用 Firebase Database 快速入门应用(适用于 SwiftUI)作为此 Codelab 的基础。

从命令行克隆 Firebase 快速入门(iOS 版)代码库

git clone https://github.com/firebase/quickstart-ios.git
cd quickstart-ios

在 Xcode 中打开 Realtime Database SwiftUI 快速入门应用项目:

cd database/DatabaseExampleSwiftUI/DatabaseExample
xed .

3. 向应用添加 App Check

  1. 等待 Swift Package Manager 解析项目的依赖项。
  2. 打开 DatabaseExample (iOS) 应用目标的常规标签页。然后,在框架、库和嵌入式内容部分中,点击 + 按钮。
  3. 选择以添加 FirebaseAppCheck

4. 创建并安装 App Check 提供程序工厂

  1. Shared 文件组中,添加一个名为 AppCheck 的新组。
  2. 在此群组内,在单独的文件(例如 MyAppCheckProviderFactory.swift)中创建一个工厂类,并确保将其添加到 DatabaseExample (iOS) 目标:
    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.
          return AppCheckDebugProvider(app: app)
        #else
          // Use App Attest provider on real devices.
          return AppAttestProvider(app: app)
        #endif
      }
    }
    
  3. 接下来,在 DatabaseExampleApp.swift 中,确保导入 FirebaseAppCheck,并将 MyAppCheckProviderFactory 类的实例设置为 App Check 提供方工厂。
    import SwiftUI
    import FirebaseCore
    import FirebaseAppCheck
    
    @main
    struct DatabaseExampleApp: App {
      init() {
        // Set an instance of MyAppCheckProviderFactory as an App Check
        // provider factory before configuring Firebase.
        AppCheck.setAppCheckProviderFactory(MyAppCheckProviderFactory())
        FirebaseApp.configure()
      }
      ...
    }
    

5. 创建并配置 Firebase 项目

如需在 iOS 项目中使用 App Check,您需要在 Firebase 控制台中按以下步骤操作:

  • 设置 Firebase 项目。
  • 将您的 iOS 应用添加到 Firebase 项目。
  • 配置 Firebase 身份验证。
  • 初始化您要保护的 Realtime Database 实例。
  • 配置 App Check。

创建项目

首先,您需要创建一个 Firebase 项目。

  1. Firebase 控制台中,选择添加项目
  2. 将项目命名为 App Check Codelab
  3. 点击继续
  4. 在此项目中停用 Google Analytics,然后点击创建项目

创建 Realtime Database 实例

现在,前往 Firebase 控制台的 Realtime Database 部分。

  1. 点击创建数据库按钮,开始数据库创建工作流。
  2. 将数据库的默认位置 (us-central1) 保持不变,然后点击下一步
  3. 确保锁定模式处于选中状态,然后点击启用按钮,为您的数据库启用安全规则。
  4. 前往 Realtime Database 浏览器中的规则标签页,然后将默认规则替换为以下规则:
    {
        "rules": {
            // User profiles are only readable/writable by the user who owns it
            "users": {
                "$UID": {
                    ".read": "auth.uid == $UID",
                    ".write": "auth.uid == $UID"
                }
            },
            // Posts can be read by anyone but only written by logged-in users.
            "posts": {
                ".read": true,
                ".write": "auth.uid != null",
                "$POSTID": {
                    // UID must match logged in user and is fixed once set
                    "uid": {
                        ".validate": "(data.exists() && data.val() == newData.val()) || newData.val() == auth.uid"
                    },
                    // User can only update own stars
                    "stars": {
                        "$UID": {
                            ".validate": "auth.uid == $UID"
                        }
                    }
                }
            },
            // User posts can be read by anyone but only written by the user that owns it,
            // and with a matching UID
            "user-posts": {
                ".read": true,
                "$UID": {
                    "$POSTID": {
                        ".write": "auth.uid == $UID",
                        ".validate": "data.exists() || newData.child('uid').val() == auth.uid"
                    }
                }
            },
            // Comments can be read by anyone but only written by a logged in user
            "post-comments": {
                ".read": true,
                ".write": "auth.uid != null",
                "$POSTID": {
                    "$COMMENTID": {
                        // UID must match logged in user and is fixed once set
                        "uid": {
                            ".validate": "(data.exists() && data.val() == newData.val()) || newData.val() == auth.uid"
                        }
                    }
                }
            }
        }
    }
    
  5. 点击发布按钮以激活更新后的安全规则。

准备好将您的 iOS 应用连接到 Firebase

如需在实体设备上运行示例应用,您需要将项目添加到您的开发团队,以便 Xcode 为您管理所需的配置文件。请按照以下步骤将示例应用添加到您的开发者账号:

  1. 在 Xcode 中,选择项目导航器中的 DatabaseExample 项目。
  2. 选择 DatabaseExample (iOS) 目标,然后打开 Signing & Capabilities(签名和功能)标签页。
  3. 您应该会看到一条错误消息,指出 DatabaseExample (iOS) 的签名需要开发团队
  4. 软件包标识符更新为唯一标识符。实现此目的的最简单方法是使用您网站的反向域名,例如 com.acme.samples.firebase.quickstart.DatabaseExample(请勿使用此 ID;请选择您自己的唯一 ID)。
  5. 选择您的开发团队。
  6. 当 Xcode 显示“Provisioning Profile: Xcode Managed Profile”(配置描述文件:Xcode 管理的描述文件)且此标签旁边显示一个信息图标时,表示一切顺利。点击此图标可显示有关配置配置文件的更多详细信息。

关联您的 iOS 应用

如需详细了解如何关联应用,请参阅有关将 Firebase 添加到 iOS 项目的文档。如需开始使用,请在 Firebase 控制台中按以下主要步骤操作:

  1. 在新项目的项目概览界面中,点击 + 添加应用按钮,然后点击 iOS+ 图标,将新的 iOS 应用添加到您的 Firebase 项目中。
  2. 输入应用的软件包 ID(使用您在上一部分中定义的 ID,例如 com.acme.samples.firebase.quickstart.DatabaseExample - 请注意,此 ID 必须是唯一标识符)
  3. 点击注册应用
  4. Firebase 会生成一个 GoogleService-Info.plist 文件,其中包含应用所需的所有 Firebase 元数据。
  5. 点击下载 GoogleService-Info.plist 以下载该文件。
  6. 在 Xcode 中,您会看到项目已包含一个名为 GoogleService-Info.plist 的文件。请先删除此文件,您将在下一步中将其替换为您自己的 Firebase 项目所对应的文件。
  7. 将您在上一步中下载的 GoogleService-Info.plist 文件复制到 Xcode 项目的根文件夹中,并将其添加到 DatabaseExample (iOS) 目标,确保其名称为 GoogleService-Info.plist
  8. 点击完成注册流程的其余步骤。由于示例项目已正确设置,因此您无需对代码进行任何更改。

配置 Firebase Authentication

大功告成!到目前为止,我们已经完成了很多设置,但请耐心等待!如果您刚开始接触 Firebase,那么您已经了解了工作流程的基本部分,很快就会熟悉这些流程。

现在,您将为此应用配置 Firebase Authentication。

启用身份验证电子邮件地址/密码登录提供程序

  1. 仍在 Firebase 控制台中,打开控制台的身份验证部分。
  2. 点击开始,为您的项目设置 Firebase Authentication。
  3. 选择登录方法标签页。
  4. 原生提供方部分中,选择电子邮件地址/密码
  5. 启用电子邮件地址/密码,然后点击保存

添加测试用户

  1. 打开 Authentication 部分的 Users 标签页。
  2. 点击添加用户
  3. 为测试用户指定电子邮件地址和密码,然后点击添加用户

试用该应用

返回 Xcode,然后在 iOS 模拟器上运行应用。使用您刚刚创建的测试用户的电子邮件地址和密码登录。登录后,您可以创建帖子、针对现有帖子发表评论,以及为帖子加星标/取消加星标。

6. 配置 App Attest 证明提供方

在此步骤中,您将在 Firebase 控制台中配置 App Check 以使用 App Attest 提供方。

  1. 在 Firebase 控制台中,前往控制台的 App Check 部分。
  2. 点击开始使用
  3. 应用标签页中,点击您的应用以展开其详细信息。
  4. 点击 App Attest 以配置 App Attest,然后输入您的 Apple 开发者账号的团队 ID(您可以在 Apple 开发者门户网站的会员部分中找到此 ID):1645f7a369b678c2.png
  5. 点击保存

这样一来,您就拥有了一个与新应用相关联的正常运行的 Firebase 项目,并且已启用 App Check。

现在,您可以开始配置我们的特定证明服务了!如需详细了解此工作流,请参阅在 iOS 上使用 App Attest 启用 App Check

7. 为应用配置 App Attest

现在,您可以开始使用 Firebase App Check SDK 并实现一些客户端代码了。

首先,您需要配置 Xcode 项目,以便 SDK 可以使用 Apple 的 App Attest API 来确保从您的应用发送的请求来自应用的合法实例。

  1. 在 Xcode 项目中,为应用目标添加 App Attest 功能:
  2. 打开应用目标设置中的 Signing & Capabilities(签名和功能)标签页
  3. 点击“+”按钮
  4. 在对话框中,找到并选择 App Attest 功能 ae84cd988a5fab31.png
  5. 执行上一步后,Xcode 项目的根文件夹中会显示一个 DatabaseExample (iOS).entitlements 文件。
  6. DatabaseExample (iOS).entitlements 文件中,将 App Attest Environment 键的值更改为 production.

完成这些步骤并在 实体 iOS 设备 (iPhone/iPad) 上启动应用后,该应用仍将能够访问 Realtime Database。在后续步骤中,您将强制执行 App Check,以阻止从非法应用和设备发送的请求。

如需详细了解此工作流,请参阅在 iOS 上使用 App Attest 启用 App Check

8. 为 iOS 模拟器配置调试证明提供方

借助 Firebase App Check 调试提供程序,您可以在开发过程中,在不受信任的环境(包括 iOS 模拟器)中测试应用,并强制执行 Firebase App Check。接下来,您需要一起配置调试提供程序。

在应用中安装 Firebase 调试提供程序

方法 1:在工厂中有条件地创建调试提供程序的实例

您在创建 App Check 提供方工厂时已完成大部分操作。在此步骤中,您将添加由调试提供程序生成的本地调试密钥的日志记录,以便在 Firebase 控制台中注册此应用实例以进行调试。

使用以下代码更新 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
    // Use App Attest provider on real devices.
    return AppAttestProvider(app: app)
#endif
  }
}

这种方法使我们能够更灵活地根据环境配置 App Check。例如,在 App Attest 不可用的操作系统版本上,您可以使用其他证明提供方(例如 DeviceCheck)或自定义证明提供方。请参阅下面的示例:

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 App Attest provider on real devices.
        return AppAttestProvider(app: app)
      } else {
        return DeviceCheckProvider(app: app)
      }
      #endif
  }
}

方法 2:安装 AppCheckDebugProviderFactory

对于更简单的情况,您可以在配置 Firebase 应用实例之前临时或有条件地安装 AppCheckDebugProviderFactory

init() {
#if targetEnvironment(simulator)
  let providerFactory = AppCheckDebugProviderFactory()
#else
  let providerFactory = MyAppCheckProviderFactory()
#endif

  AppCheck.setAppCheckProviderFactory(providerFactory)

  FirebaseApp.configure()
}

这样一来,您在创建自己的 App Check 提供程序工厂时,就可以少写几行代码。

在 Firebase 控制台中注册调试密钥

从 iOS 模拟器获取调试密钥

  1. 如果您选择安装 AppCheckDebugProviderFactory(上述方法 2),则需要通过向应用启动实参添加 -FIRDebugEnabled 来为应用启用调试日志记录功能:f1c6b477a373e144.png
  2. 在模拟器上运行应用
  3. 在 Xcode 控制台中找到调试 Secret。您可以使用控制台过滤条件更快地找到它:d4c65af93e369c55.png

注意:调试密钥是在首次启动应用时为模拟器生成的,并存储在用户默认设置中。如果您移除该应用、重置模拟器或使用其他模拟器,系统会生成新的调试密钥。请务必注册新的调试密钥。

注册调试密钥

  1. 返回 Firebase 控制台,前往 App Check 部分。
  2. 应用标签页中,点击您的应用以展开其详细信息。
  3. 在溢出菜单中,选择管理调试令牌d77c8ff768a00b4b.png
  4. 添加从 Xcode 控制台复制的密钥,然后点击保存 图标 f845c97b86f694d0.png

完成这些步骤后,即使强制执行 App Check,您也可以在模拟器上使用该应用。

注意:调试提供程序专门用于帮助防止调试密钥泄露。使用当前方法,您无需在源代码中存储调试密钥。

如需详细了解此流程,请参阅相关文档 - 在 iOS 上将 App Check 与调试提供程序搭配使用

9. 为 Firebase Realtime Database 启用 App Check 强制执行

目前,我们的应用声明了一个 AppCheckProviderFactory,该 AppCheckProviderFactory 会为真机设备返回一个 AppAttestProvider。在实体设备上运行时,您的应用将执行证明并向 Firebase 后端发送结果。不过,Firebase 后端仍会接受来自任何设备、iOS 模拟器、脚本等的请求。如果您仍有用户使用没有 App Check 的旧版应用,并且您不想强制执行访问检查,则此模式非常有用。

现在,您需要启用 App Check 强制执行,以确保只有正当设备可以访问 Firebase 应用。一旦您为 Firebase 项目启用强制执行,未集成 App Check 的旧版应用将停止运行。

  1. 在 Firebase 控制台的 App Check 部分中,点击 Realtime Database 以展开其详细信息。
  2. 点击强制执行

64e6a81fa979b635.png

  1. 阅读确认对话框中的信息,然后点击强制执行

完成这些步骤后,只有合法应用才能访问数据库。所有其他应用都会被屏蔽。

尝试使用非法应用访问 Realtime Database

如需查看 App Check 的实际强制执行效果,请按以下步骤操作:

  1. 通过在 DatabaseExampleApp 中应用入口点的 init 方法中注释掉 App Check 注册代码,关闭 App Check 注册。
  2. 选择设备 > 抹掉所有内容和设置,重置模拟器。此操作会擦除模拟器(并使设备令牌失效)。
  3. 在模拟器上再次运行应用。
  4. 您现在应该会看到以下错误消息:
    [FirebaseDatabase][I-RDB034005] Firebase Database connection was forcefully killed by the server.  Will not attempt reconnect. Reason: Invalid appcheck token.
    

如需重新启用 App Check,请执行以下操作:

  1. 取消注释 DatabaseExampleApp 中的 App Check 注册代码。
  2. 重启应用。
  3. 记下 Xcode 控制台中的新 App Check 令牌。
  4. 在 Firebase 控制台中,在应用的 App Check 设置中注册调试令牌。
  5. 重新运行应用。
  6. 您应该不会再看到错误消息,并且应该能够在应用中添加新帖子和评论。

10. 恭喜!

9785d32f18b995d2.gif

现在,您已了解如何:

  • 向现有项目添加 App Check
  • 为应用的正式版配置 App Attest 证明提供方
  • 配置调试证明提供方,以便在模拟器上测试应用
  • 观察应用版本发布情况,了解何时为 Firebase 项目强制执行 App Check
  • 启用 App Check 强制执行

后续步骤

如需了解如何使用 Remote Config 逐步向用户推出 App Check,请参阅 Codelab:使用 Firebase Remote Config 逐步推出 Firebase App Check

以下是一些可能对您有用的其他资源

此 Codelab 中介绍的设置适用于大多数情况,但如果需要,您可以使用 App Check 获得更大的灵活性 - 请查看以下链接了解详情: