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,然后强制执行 App Check,以确保聊天应用的安全。

由您构建的初始 Friendly Chat 应用。

学习内容

  • 如何监控后端是否有未经授权的访问
  • 如何为 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 的起始代码,该代码将是一个功能齐全的聊天网络应用。📁?appcheck 目录将包含此 Codelab 的完成代码。

3. 创建和设置 Firebase 项目

创建 Firebase 项目

  1. 登录 Firebase
  2. 在 Firebase 控制台中,点击“添加项目”,然后将您的 Firebase 项目命名为“FriendlyChat”。记住您的 Firebase 项目的项目 ID。
  3. 取消选中“为此项目启用 Google Analytics”
  4. 点击“创建项目”。

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

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

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

升级您的 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 的后面部分复制此对象,因此现在请按 Next(下一步)。

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

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

为 Firebase Authentication 启用 Google 登录

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

您需要启用 Google 登录:

  1. 在 Firebase 控制台中,在左侧面板中找到构建部分。
  2. 点击 Authentication,点击 Get Started(如果适用),然后点击 Sign-in method 标签页(或点击此处直接转到该标签页)。
  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. 为默认的 Storage 存储分区选择位置。
    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 应用部署到 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 控制台的“Hosting”部分下找到您的托管域名。填写完这些信息后,按 Done(完成)和 Create Key(创建密钥)。

reCAPTCHA 创建密钥屏幕

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

reCAPTCHA Enterprise 注册窗口

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

用于注册 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,而无需担心为应用的真实客户端关闭访问权限。这还可以告诉您,有多少次尝试访问后端的请求并非来自应用内部。这可能是因为用户在您不知情的情况下直接查询您的后端。既然您可以看到请求未经验证,那么在继续验证这些请求之前,不妨先看看那些可能向您的后端发送了未经验证的请求的用户会遇到什么情况。

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

继续按上一个屏幕中的强制执行按钮,然后在系统提示时再次按强制执行

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

这将开始强制执行 App Check;现在,如果有请求未通过您选择的认证提供程序(在本例中为 reCAPTCHA Enterprise)进行验证,App Check 会阻止该请求访问您的后端服务。返回到应该在 http://localhost:5000 上运行的正在运行的 Web 应用。刷新页面并尝试从数据库中获取数据时,没有任何反应。如果您打开 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 添加到以下平台:

参考文档