Firebase App Check(Apple 平台)

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 开发者账号,用于创建新的应用标识符
  • 支持 App Attest 的 iOS/iPadOS 设备(了解 App Attest API 可用性

2. 获取入门级项目

适用于 iOS 的 Firebase 快速入门代码库包含示例应用,用于演示不同的 Firebase 产品。您将使用 SwiftUI 的 Firebase 数据库快速入门应用作为此 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) 应用目标的常规标签页。然后,在 Frameworks, Libraries and Embedded Content 部分中,点击 + 按钮。
  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 Authentication。
  • 初始化要保护的 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) 目标,然后打开签名和功能标签页。
  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. 在新项目的 Project Overview 屏幕中,点击 + Add app 按钮,然后点击 iOS+ 图标,向您的 Firebase 项目添加新的 iOS 应用。
  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 控制台中,打开控制台的 Authentication 部分。
  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 Developer 账号的团队 ID(可以在 Apple Developer 门户的 Membership 部分中找到此信息):1645f7a369b678c2
  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. 请打开签署和应用定位设置中的“功能”标签
  3. 点击“+”按钮
  4. 在对话框中,找到并选择 App Attest 功能 ae84cd988a5fab31
  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 Debug 提供方,您可以在开发过程中在不受信任的环境(包括 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 来为应用启用调试日志记录功能:f1c6b477a373e144
  2. 在模拟器上运行应用
  3. 在 Xcode 控制台中找到调试 Secret。您可以使用控制台过滤条件更快地找到它:d4c65af93e369c55.png

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

注册调试密钥

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

完成上述步骤后,即使强制执行应用检查,您也可以在模拟器上使用该应用。

注意:调试提供程序专为帮助防止调试密钥泄露而设计。采用当前方法时,您无需将调试密钥存储在源代码中。

如需详细了解此流程,请参阅相关文档 - 在 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

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

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

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

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

  1. 如需关闭 App Check 注册,请在 DatabaseExampleApp 的应用入口点的 init 方法中注释掉 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,请参阅“使用 Firebase Remote Config 逐步部署 Firebase App Check”Codelab

以下是可能对您有帮助的其他资源

此 Codelab 中介绍的设置适用于大多数情况,但在需要时,您可以通过 App Check 实现更灵活的设置 - 请访问以下链接了解详情: