适用于 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 开发者账号
  • 支持 App Attest 的 iOS/iPadOS 设备(了解 App Attest API 可用性

2. 获取入门级项目

Firebase 快速入门 (iOS) 代码库包含演示不同 Firebase 产品的示例应用。您将使用适用于 SwiftUI 的 Firebase Realtime Database 快速入门应用作为此 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) 应用目标的 General 标签页。然后,在框架、库和嵌入内容部分中,点击 + 按钮。
  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. 您应该会看到如下错误消息:“Signing for DatabaseExample (iOS) requires a Development team”(签名数据库示例 (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 控制台中,打开控制台的 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 开发者账号的团队 ID(您可以在 Apple 开发者门户的会员资格部分找到此 ID):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.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 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
  2. 在模拟器上运行应用
  3. 在 Xcode 控制台中找到调试密钥。您可以使用控制台过滤条件更快地找到它:d4c65af93e369c55

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

注册调试密钥

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

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

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

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

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

目前,我们的应用声明了 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. 通过选择 Device >清除所有内容和设置。这将擦除模拟器(并使设备令牌失效)。
  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 实现更灵活的设置 - 请访问以下链接了解详情: