App Check Web Codelab

1. 简介

上次更新日期:2023 年 2 月 23 日

如何防止未经授权的用户访问您的 Firebase 资源?

您可以使用 Firebase App Check 来防止未经授权的客户端访问您的后端资源,方法是要求传入的请求附带证明请求来自您的正版应用的证明,并阻止没有适当证明的流量。Firebase App Check 依赖于平台专用的证明提供方来验证客户端的真实性:对于 Web 应用,App Check 支持 reCAPTCHA v3 和 reCAPTCHA Enterprise 作为证明提供方。

App Check 可用于保护对 Cloud Firestore、Realtime Database、Cloud Functions、Firebase Authentication with Identity Platform 以及您自行托管的后端的请求。

构建内容

在此 Codelab 中,您将通过先添加然后强制执行 App Check 来保护聊天应用。

由您构建的初始友好聊天应用。

学习内容

  • 如何监控后端以防未经授权的访问
  • 如何为 Firestore 和 Cloud Storage 添加强制执行
  • 如何使用调试令牌运行应用以进行本地开发

所需条件

  • 您选择的 IDE/文本编辑器
  • 软件包管理器 npm(通常随 Node.js 一起安装)
  • Firebase CLI 已安装并配置为可与您的账号搭配使用
  • 终端/控制台
  • 您所选的浏览器(例如 Chrome)
  • Codelab 的示例代码(如需了解如何获取代码,请参阅 Codelab 的下一步。)

2. 获取示例代码

从命令行克隆 Codelab 的 GitHub 代码库

git clone https://github.com/firebase/codelab-friendlychat-web

或者,如果您未安装 Git,也可以下载代码库 ZIP 文件

导入 starter 应用

使用 IDE 打开或导入克隆的代码库中的 📁 appcheck-start 目录。此 📁 appcheck-start 目录包含 Codelab 的起始代码,该代码将是一个功能完善的聊天 Web 应用。📁 appcheck 目录将包含 Codelab 的已完成代码。

3. 创建和设置 Firebase 项目

创建 Firebase 项目

  1. 使用您的 Google 账号登录 Firebase 控制台
  2. 点击相应按钮以创建新项目,然后输入项目名称(例如 FriendlyChat)。
  3. 点击继续
  4. 如果看到相关提示,请查看并接受 Firebase 条款,然后点击继续
  5. (可选)在 Firebase 控制台中启用 AI 辅助功能(称为“Gemini in Firebase”)。
  6. 在此 Codelab 中,您不需要使用 Google Analytics,因此请关闭 Google Analytics 选项。
  7. 点击创建项目,等待项目完成预配,然后点击继续

升级您的 Firebase 定价方案

如需使用 Cloud Storage for Firebase,您的 Firebase 项目必须采用随用随付 (Blaze) 定价方案,这意味着该项目与一个 Cloud Billing 账号相关联。

  • Cloud Billing 账号要求提供付款方式,例如信用卡。
  • 如果您刚开始接触 Firebase 和 Google Cloud,请确认您是否有资格获得 $300 赠金和免费试用 Cloud Billing 账号
  • 如果您是在活动中完成此 Codelab,请询问活动组织者是否有可用的 Cloud 积分。

如需将项目升级到 Blaze 方案,请按以下步骤操作:

  1. 在 Firebase 控制台中,选择升级您的方案
  2. 选择 Blaze 方案。按照屏幕上的说明将 Cloud Billing 账号与您的项目相关联。
    如果您需要在此升级过程中创建 Cloud Billing 账号,则可能需要返回 Firebase 控制台中的升级流程以完成升级。

向项目添加 Firebase Web 应用

  1. 点击 Web 图标 58d6543a156e56f9.png 以创建新的 Firebase Web 应用。
  2. 注册昵称为 Friendly Chat 的应用,然后选中还为此应用设置 Firebase Hosting 旁边的复选框。点击注册应用
  3. 在下一步中,您将看到使用 npm 安装 Firebase 的命令和一个配置对象。您将在本 Codelab 的后半部分复制此对象,因此现在请按下一步

“将 Firebase 添加到您的 Web 应用”窗口

  1. 然后,您会看到安装 Firebase CLI 的选项。如果您尚未安装,请立即使用命令 npm install -g firebase-tools 进行安装。然后点击下一步
  2. 然后,您会看到一个用于登录 Firebase 并部署到 Firebase 托管的选项。继续操作,使用命令 firebase login 登录 Firebase,然后点击继续前往控制台。您将在后续步骤中部署到 Firebase Hosting。

设置 Firebase 产品

我们将要构建的应用会使用多个适用于 Web 应用的 Firebase 产品:

  • Firebase Authentication,可让用户轻松登录您的应用。
  • Cloud Firestore:用于在云端保存结构化数据,并在数据发生变化时即时收到通知。
  • Cloud Storage for Firebase,用于将文件保存在云端。
  • Firebase Hosting:用于托管和提供您的资产。
  • Firebase Cloud Messaging,用于发送推送通知和显示浏览器弹出式通知。
  • Firebase Performance Monitoring 收集应用的用户性能数据。

其中一些产品需要进行特殊配置,或需要使用 Firebase 控制台启用。

为 Firebase Authentication 启用 Google 登录

如需允许用户使用其 Google 账号登录 Web 应用,我们将使用 Google 登录方法。

您需要启用 Google 登录:

  1. 在 Firebase 控制台中,在左侧面板中找到构建部分。
  2. 点击身份验证,点击开始(如果适用),然后点击登录方法标签页(或点击此处直接转到该标签页)。
  3. 启用 Google 登录提供方
  4. 将应用的公开名称设置为 Friendly Chat,然后从下拉菜单中选择项目支持电子邮件地址。
  5. 点击保存

f96888973c3d00cc.png

设置 Cloud Firestore

Web 应用使用 Cloud Firestore 保存聊天消息并接收新的聊天消息。

以下是在 Firebase 项目中设置 Cloud Firestore 的方法:

  1. 在 Firebase 控制台的左侧面板中,展开构建,然后选择 Firestore 数据库
  2. 点击创建数据库
  3. 数据库 ID 保留为 (default)
  4. 为数据库选择一个位置,然后点击下一步
    对于真实应用,您需要选择靠近用户的位置。
  5. 点击以测试模式开始。阅读有关安全规则的免责声明。
    在本 Codelab 的后面部分,您将添加安全规则来保护您的数据。在没有为数据库添加安全规则的情况下,请不要公开分发或公开应用。
  6. 点击创建

设置 Cloud Storage for Firebase

该 Web 应用使用 Cloud Storage for Firebase 来存储、上传和分享图片。

以下是在 Firebase 项目中设置 Cloud Storage for Firebase 的方法:

  1. 在 Firebase 控制台的左侧面板中,展开构建,然后选择存储
  2. 点击开始使用
  3. 为默认存储分区选择位置。
    US-WEST1US-CENTRAL1US-EAST1 中的存储分区可为 Google Cloud Storage 使用“始终免费”层级。所有其他位置的存储分区都遵循 Google Cloud Storage 价格和用量
  4. 点击以测试模式开始。阅读有关安全规则的免责声明。
    在本 Codelab 的后面部分,您将添加安全规则来保护您的数据。在未为您的存储桶添加安全规则的情况下,请不要公开分发或公开应用。
  5. 点击创建

4. 配置 Firebase

appcheck-start 目录中,调用:

firebase use --add

当系统提示时,选择您的项目 ID,然后为您的 Firebase 项目指定一个别名。对于此项目,您只需提供别名 default。接下来,您需要配置本地项目以使用 Firebase。

  1. 前往 Firebase 控制台中的项目设置
  2. 在“您的应用”卡片中,选择您需要为其添加配置对象的应用的昵称。
  3. 从 Firebase SDK 代码段窗格中选择 Config
  4. 复制配置对象代码段,然后将其添加到 appcheck-start/hosting/src/firebase-config.js。此 Codelab 的其余部分假定该变量名为 config

firebase-config.js

const config = {
  apiKey: "API_KEY",
  authDomain: "PROJECT_ID.firebaseapp.com",
  databaseURL: "https://PROJECT_ID.firebaseio.com",
  projectId: "PROJECT_ID",
  storageBucket: "PROJECT_ID.firebasestorage.app",
  messagingSenderId: "SENDER_ID",
  appId: "APP_ID",
  measurementId: "G-MEASUREMENT_ID",
};

从同一 appcheck-start 目录中,然后调用:

firebase experiments:enable webframeworks

这会启用此项目所基于的Web 框架支持

现在,我们应该已准备就绪,可以运行项目并测试默认项目是否正常运行!

5. 在不使用 App Check 的情况下试用应用

现在,您已配置好应用并设置好 SDK,请尝试按应用最初的设计方式使用该应用。首先,安装所有依赖项。在终端中,前往 appcheck-start/hosting 目录。在该目录下,运行 npm install。此命令会提取项目正常运行所需的所有依赖项。如需在应用的当前状态下启动应用,您可以运行 firebase serve。该应用会要求您使用 Google 账号登录;请登录,然后尝试向聊天内容发布几条聊天消息和几张照片。

现在您已在本地测试了该应用,接下来可以在生产环境中查看它了!运行 firebase deploy 以将 Web 应用部署到网络。此部分是演示 App Check 在实际应用中如何运作的关键步骤,因为它需要为 reCAPTCHA Enterprise 证明提供程序配置网域。

希望您能体验到应用提供的默认功能。发布聊天消息以及其他只能通过此类应用完成的操作。当前状态的缺点是,任何拥有上一步中应用配置的人都可以访问您的后端资源。他们仍然需要遵守 Firestore 和 Cloud Storage 系统中现有的安全规则,但除此之外,他们仍然可以查询、存储和访问存储在那里的数据。

在接下来的几个步骤中,您将:

  • 注册 App Check
  • 验证强制执行
  • 开始强制执行规则

6. 启用 App Check 并强制执行

我们先来获取项目的 reCAPTCHA Enterprise 密钥,然后将其添加到 App Check 中。首先,您需要前往 Google Cloud 控制台的 reCAPTCHA Enterprise 部分。选择您的项目,然后系统会提示您启用 reCAPTCHA Enterprise API。启用该 API,然后等待几分钟,直到完成。然后,点击企业密钥旁边的创建密钥。然后,在此部分中,指定显示名称并选择网站类型的密钥。您需要指定托管应用的网域。由于您计划在 Firebase Hosting 上托管此应用,因此请使用默认托管名称,该名称通常为 ${YOUR_PROJECT_ID}.web.app。您可以在 Firebase 控制台的托管部分下找到您的托管网域。填写完这些信息后,按完成创建密钥

reCAPTCHA 创建密钥界面

完成后,您会在关键详情页面顶部看到一个 ID。

reCAPTCHA Enterprise 注册窗口

接下来,将此 ID 复制到剪贴板。这是您用于 App Check 的密钥。接下来,前往 Firebase 控制台的 App Check 部分,然后点击开始。然后,依次点击注册reCAPTCHA Enterprise,并将复制的 ID 放入 reCAPTCHA Enterprise 网站密钥的文本框中。将其余设置保留为默认值。您的 App Check 页面应如下所示:

您注册 reCAPTCHA Enterprise 令牌的“App Check 应用”窗口

未验证且未强制执行的请求

现在,您已在 Firebase 控制台中注册密钥,请通过运行 firebase serve 重新在浏览器中运行您的网站。现在,您可以在本地运行 Web 应用,并再次开始针对 Firebase 后端发出请求。由于请求是针对 Firebase 后端的,因此 App Check 会监控这些请求,但不会强制执行。如果您想查看传入请求的状态,可以访问 Firebase 控制台中 App Check 页面的 API 标签页中的 Cloud Firestore 部分。由于您尚未配置客户端以使用 App Check,因此您应该会看到类似以下内容的输出:

一个 App Check 信息中心,显示了您应用的所有客户端请求均未经过验证。

后端收到的请求 100% 未经过验证。此界面非常有用,因为它显示几乎所有客户端请求都来自未集成 App Check 的客户端。

此信息中心可显示以下几项内容。首先,它可以指示所有客户端应用是否都在运行最新版本的客户端。如果它们是,那么您可以放心地强制执行 App Check,而不必担心会关闭应用的真实客户端的访问权限。此指标可能还会显示有多少次尝试访问您的后端不是来自您的应用。这可能意味着有用户在您不知情的情况下直接查询您的后端。既然您可以看到请求未经过验证,那么在继续验证这些用户的请求之前,不妨先看看如果这些用户向您的后端发送了未经验证的请求,会发生什么情况。

未验证且已强制执行的请求

继续操作,按上一个界面中的 Enforce 按钮,然后在系统提示时再次按 Enforce

一个未经验证的指标信息中心,其中突出显示了“强制执行”按钮

这会开始强制执行 App Check;现在,系统会阻止对后端服务的请求,除非这些请求通过您选择的证明提供方(在本例中为 reCAPTCHA Enterprise)进行了验证。返回到正在运行的 Web 应用,该应用应在 http://localhost:5000 处运行。当您刷新页面并尝试从数据库获取数据时,没有任何反应。如果您打开 Chrome 控制台来读取错误,应该会看到类似以下内容:

Uncaught Error in snapshot listener: FirebaseError: [code=permission-denied]: Missing or insufficient permissions.

这是 App Check 阻止了未在其对 Firebase 资源的请求中传递有效证明令牌的请求。目前,您可以关闭 App Check 强制执行,并在下一部分中了解如何将 reCAPTCHA Enterprise App Check 添加到 Friendly Chat 示例中。

7. 向网站添加 reCAPTCHA Enterprise 密钥

我们将向您的应用添加企业密钥。首先,打开 hosting/src/firebase-config.js 并将您的 reCAPTCHA Enterprise 密钥添加到以下代码段:

const reCAPTCHAEnterpriseKey = {
  // Replace with your recaptcha enterprise site key
  key: "Replace with your recaptcha enterprise site key"
};

完成此操作后,打开 hosting/src/index.js,然后在第 51 行添加来自 firebase-config.js 的导入,以获取 reCAPTCHA 密钥,并导入 App Check 库,以便您使用 reCAPTCHA Enterprise 提供方。

// add from here
 import {
   initializeAppCheck,
   ReCaptchaEnterpriseProvider,
 } from 'firebase/app-check';
// to here

// replace this line
import { getFirebaseConfig } from './firebase-config.js';
// with this line
import { getFirebaseConfig, getReCaptchaKey } from './firebase-config.js';

然后,在下一行中,您将创建一个函数来设置 App Check。该函数将首先检查您是否处于开发环境中,如果是,则打印可用于本地开发的调试令牌。

import { getFirebaseConfig, getReCaptchaKey } from './firebase-config.js';
// add from here
 function setupAppCheck(app) {
   if(import.meta.env.MODE === 'development') {
     self.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
   }
 }
// to here

现在,您可以初始化 App Check 以与所选提供程序(在本例中为 reCAPTCHA Enterprise)搭配使用。然后,您还需要在后台自动刷新 App Check 令牌,这样可以防止用户与服务互动时因 App Check 令牌过期而出现任何类型的延迟。

function setupAppCheck(app) {
   if(import.meta.env.MODE === 'development') {
     self.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
   }
// add from here
   // Create a ReCaptchaEnterpriseProvider instance using your reCAPTCHA Enterprise
   // site key and pass it to initializeAppCheck().
   initializeAppCheck(app, {
     provider: new ReCaptchaEnterpriseProvider(getReCaptchaKey()),
     isTokenAutoRefreshEnabled: true // Set to true to allow auto-refresh.
   });
// to here
 }

最后,在确保应用已初始化后,您需要调用刚刚创建的 setupAppCheck 函数。在 hosting/src/index.js 文件的底部,添加对您最近添加的方法的调用。

const firebaseApp = initializeApp(getFirebaseConfig());
// add from here
setupAppCheck(firebaseApp);
// to here
getPerformance();
initFirebaseAuth();
loadMessages();

先在本地进行测试

请先在本地测试应用。如果您尚未在本地提供应用,请运行 firebase serve。您应该会注意到,应用仍然无法在本地加载。这是因为您只向 reCAPTCHA 证明提供方注册了 Firebase 网域,而未注册 localhost 网域。您绝不应将 localhost 注册为获批网域,因为这会允许用户从其机器上本地运行的应用访问受限后端。不过,由于您设置了 self.FIREBASE_APPCHECK_DEBUG_TOKEN = true,因此您需要在 JavaScript 控制台中查找类似如下所示的行:

App Check debug token: 55183c20-de61-4438-85e6-8065789265be. You will need to add it to your app's App Check settings in the Firebase console for it to work.

您需要获取提供的调试令牌(在本示例中为:55183c20-de61-4438-85e6-8065789265be),然后将其插入应用的溢出菜单下的 App Check 配置中。

显示“管理调试令牌”位置的 App Check 信息中心

为令牌指定一个便于您记住的唯一名称,然后点击保存。此选项允许您在应用中使用客户端生成的令牌,这是一种比生成调试令牌并将其嵌入应用中更安全的替代方案。在应用中嵌入令牌可能会导致令牌意外分发给最终用户,而这些最终用户可能会利用该令牌绕过您的检查。如果您希望在 CI 环境中分发调试令牌,请参阅此文档,详细了解如何分发调试令牌。

使用别名填充调试令牌的示例

在 Firebase 控制台中注册调试令牌后,您可以重新启用 App Check 强制执行,并通过从终端调用 firebase serve 来测试应用内容是否在本地加载。您应该会看到之前输入的数据被提供给本地版本的 Web 应用。您应该仍然会在控制台中看到包含调试令牌的消息。

在正式版中试用

确认 App Check 在本地正常运行后,将 Web 应用部署到生产环境。在终端中再次调用 firebase deploy 并重新加载页面。此命令会将您的 Web 应用打包,以便在 Firebase Hosting 上运行。将应用托管在 Firebase Hosting 上后,尝试访问 ${YOUR_PROJECT_ID}.web.app 中的应用。您可以打开 JavaScript 控制台,此时应该不会再看到调试令牌打印在那里,并且应该会看到聊天内容在您的项目中加载。此外,在与应用互动片刻后,您可以访问 Firebase 控制台的“App Check”部分,验证对应用的请求是否已全部切换为经过验证。

8. 恭喜!

恭喜!您已成功将 Firebase App Check 添加到 Web 应用中!

您可以设置 Firebase 控制台来处理生产环境的 reCAPTCHA Enterprise 令牌,甚至可以为本地开发设置调试令牌。这样可确保您的应用仍能从获批的客户端访问 Firebase 资源,并防止应用内发生欺诈活动。

后续操作

如需将 Firebase App Check 添加到以下平台,请查看以下文档:

参考文档