使用 App Check 保护您的 Maps JavaScript API 密钥

1. 准备工作

显示正常运行的应用的页面

您将构建的内容。

在此 Codelab 中,您将使用 App Check 为在 Web 环境中使用的 API 密钥添加另一层保护。

具体而言,您将在本 Codelab 中完成以下步骤,以将各项功能整合在一起:

  • 使用 Google Maps Platform JavaScript API 创建网页来托管地图。
  • 托管该网页,以便在线访问。
  • 使用 Cloud 控制台限制可以使用该 API 的网域和 API。
  • 通过 Firebase 添加并初始化 App Check 库。
  • 添加证明提供程序以检查应用的有效性。
  • 强制对应用和显示器进行检查。

完成本 Codelab 后,您应该会获得一个可正常运行的网站,该网站会对所使用的 API 密钥、访问这些密钥的网域以及可以使用这些密钥的应用类型强制执行安全措施。

2. 前提条件

启用 App Check 需要使用三项 Google 服务来提供保护,您应熟悉这些方面。

Firebase - 这项服务可强制执行检查,确保 API 密钥是从相应网域引用的。此外,它还将通过使用 Firebase Studio 提供托管和部署功能。

reCAPTCHA - 此功能可用于检查是否有人在使用应用,还可提供用于将 Firebase 连接到客户端应用网域的公钥和私钥。

Google Cloud Platform - 这会提供 Google Maps Platform 和 Firebase 使用的 API 密钥,以及对使用 Maps 密钥的网域的限制。

您可以在以下架构图中查看这些组件如何协同工作:

系统架构概览

使用 App Check 和 Google Maps Platform 时,以下元素会协同工作,以确定请求是否来自有效的应用和用户,并使用证明提供方(在本例中为 reCAPTCHA)提供的证明。

这是通过使用 Firebase 提供的 App Check SDK 来实现的,该 SDK 会检查调用应用的有效性,然后向应用提供一个令牌,应用可通过该令牌后续调用 Google Maps Platform JavaScript API。然后,Google Maps Platform JavaScript API 会通过 Firebase 检查所提供令牌的有效性,以确保该令牌不仅来自正确的网域,而且是通过证明提供方从有效用户处获得的。

您可以在以下位置找到有关使用 App Check 和 Maps JavaScript API 的更多详细信息,并且应熟悉所需步骤。

https://developers.google.com/maps/documentation/javascript/maps-app-check

3. 进行设置

如果您还没有 Google Cloud 账号,则需要在开始时设置一个已启用结算功能的账号。请按照说明在开始之前创建此文件。

设置 Google Maps Platform

如果您还没有已启用结算功能的 Google Cloud Platform 账号和项目,请参阅 Google Maps Platform 使用入门指南,创建结算账号和项目。

  1. Cloud Console 中,点击项目下拉菜单,选择要用于此 Codelab 的项目。

  1. Google Cloud Marketplace 中启用此 Codelab 所需的 Google Maps Platform API 和 SDK。为此,请按照此视频此文档中的步骤操作。
  2. 在 Cloud Console 的凭据页面中生成 API 密钥。您可以按照此视频此文档中的步骤操作。向 Google Maps Platform 发出的所有请求都需要 API 密钥。

完成此 Codelab 的其他要求

要完成此 Codelab,您需要以下账号、服务和工具:

  • 具备 JavaScript、HTML 和 CSS 方面的基础知识
  • 已启用结算功能的 Google Cloud 账号(如上所述)
  • 已启用 Maps JavaScript API 的 Google Maps Platform API 密钥(此操作将在 Codelab 期间完成)。
  • 对 Web 托管和部署有基本的了解(您将在 Codelab 中获得相关指导)。此过程将通过 Firebase 控制台和 Firebase Studio 完成。
  • 一个网络浏览器,用于在您工作时查看文件。

4. 在 Firebase Studio 中创建网页

此 Codelab 假设您尚未创建应用,并使用 Firebase Studio 创建一个用于托管地图应用的网页,并将其部署到 Firebase 以进行测试。如果您有现有应用,也可以使用该应用,但需要更改相应的主机网域、代码段和 API 密钥,以确保正确实现。

前往 Firebase Studio(需要 Google 账号),然后创建一个新的简单 HTML 应用,您可能需要点击“查看所有模板”按钮才能显示此选项,或者只需点击此链接即可直接访问。

显示简单 HTML 模板的图片

为工作区指定一个合适的名称,例如 myappcheck-map(加上一些随机数字以确保唯一性,系统会自动添加)。然后,Firebase Studio 将创建工作区。

图片:显示新的工作区选项

填写名称后,您可以点击“创建”按钮,系统随即会开始创建项目。

显示项目创建对话框的图片

创建完成后,您可以将 index.html 文件中的文本替换为以下代码,该代码会创建一个包含地图的网页。

<!doctype html>
<html>

<head>
 <title>Secure Map</title>
 <style>
   #map {
     height: 100%;
   }

   html,
   body {
     height: 100%;
     margin: 0;
     padding: 0;
     font-family: Arial, Helvetica, sans-serif;
   }
 </style>
</head>

<body>
 <h3>App Check Security Demo</h3>
 <!--The div element for the map -->
 <div id="map"></div>
 <script>
   (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
     key: "YOUR_API_KEY",
     v: "weekly",
     // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
     // Add other bootstrap parameters as needed, using camel case.
   });
 </script>
 <script>
   let map;
   async function initMap() {
     const { Map } = await google.maps.importLibrary("maps");
     map = new Map(document.getElementById("map"), {
       center: { lat: 51.5208, lng: -0.0977 },
       zoom: 17,
     });
   }
   initMap();
 </script>
</body>

</html>

运行后,应该会显示一个页面,其中包含工作应用的地图,如图所示,但是!

显示正常运行的应用的图片。

不过,当实际加载网页时,系统会显示错误,因为网页中需要 Google Maps Platform API 密钥,我们将在后续部分中添加该密钥。

显示“出了点问题”通知的图片。

您可以在 Firebase Studio 的 Web 控制台中查看实际的错误消息。

密钥无效错误消息。

为了解决此问题,我们需要向网页添加 API 密钥。API 密钥是将网页与 Maps JavaScript API 实现关联起来的方式。它也是一个可被利用的区域,因为需要以未加密的方式将其包含在网页中,这样一来,API 密钥可能会被盗用并用于其他网站。

一种保护方法是使用应用限制,无论是通过所使用的应用类型还是通过所调用的引荐网域或 IP 地址。如需详细了解最佳实践,请访问以下网站:

https://developers.google.com/maps/api-security-best-practices#rec-best-practices

或者通过从命令行或服务器直接调用,这些应用本身无法提供引荐来源网址或被跟踪,因此可能存在安全漏洞。

5. 创建 Firebase 应用

Firebase 用于提供将证明提供方关联起来的功能,以检查以下各项:

  • 请求来自您的正版应用
  • 请求来自真实的、未经篡改的设备和用户会话。

在此 Codelab 中,reCAPTCHA v3 将用作此证明的提供方。

创建 Firebase 应用并进行托管。

前往 https://firebase.google.com/,然后通过前往控制台链接创建一个新的 Firebase 项目。

显示控制台链接的图片

点击以下区域,创建一个新项目。

创建新的 Firebase 项目。

为项目选择一个名称,例如 My App Check Project,不必与之前使用的名称相同,因为这只是参考名称,项目的实际名称可以在文本下方进行修改,它将由您输入的名称组成,如果不是唯一名称,则会在后面添加一个数字。

图片:显示了输入项目名称的详细信息。

如果系统提示您向应用添加其他服务(例如 Google Analytics),您可以接受或不接受,但对于此 Codelab,这些服务不是必需的,因此可以不添加。

点击“创建项目”按钮,然后等待项目创建完成。完成后,系统会通知您。

显示正在创建项目的对话框的图片。

当此项目准备好开始互动时,点击“继续”。

显示项目完成对话框的图片。

在主页面中,您可以选择将 Firebase 添加到您的应用,然后选择“网页”选项,开始使用 Firebase。

首先添加。

选择为您的网站设置 Firebase Hosting,以便在部署文件后将文件放置在某个位置(对于实际网站,您可以使用自己的选项,但为了完成此 Codelab,您需要部署到 Firebase Hosting)。

注册新应用。

点击“注册应用”以创建应用。接下来,您将使用创建的脚本从 Web 应用中引用 Firebase 中的项目。

下一个标签页中的 Firebase 配置代码将在应用中用于将 Firebase 和 Maps API 连接在一起,因此值得从“使用脚本标记”部分复制。您将此代码粘贴到项目 index.html 中。

要包含在网页中的脚本代码。

点击“下一步”查看其他部分,然后在网站的项目设置部分中查看已创建的应用。

如果您日后需要返回并查找配置的详细信息,还可以通过“设置”按钮查找应用详情,如图所示:

“项目设置”菜单项。

在离开本部分之前,您需要记下创建的 Firebase Hosting 网站的网域,以便稍后与 reCAPTCHA 搭配使用。这样一来,网站名称便会与证明提供方相关联,这意味着只有来自该网站的请求才会得到验证。

通过项目快捷方式或左侧的“构建”菜单前往 Hosting 部分

显示 Hosting 快捷方式的图片。显示托管 build 菜单的图片。

然后,从该部分查找已为应用创建的网域。如果尚未设置,您可能需要点击几个界面才能完成设置。

显示托管网域对话框的图片。

6. 保障 API 密钥安全

使用您正在 Firebase 上使用的同一账号进入 Cloud 控制台,查看已创建的项目,

链接 [link]

显示 Cloud 控制台链接的图片

如果您有多个项目,可能需要使用下拉菜单或搜索框来选择正确的项目(即您的 Firebase 项目)。

显示“选择项目”列表的图片

系统会打开新创建的项目。您现在将向此项目添加 Maps JavaScript API,以便在项目中使用该 API,包括将其使用限制为特定 API 密钥和托管网域。

显示项目欢迎页面的图片。

使用左侧的菜单在项目中启用 Maps API。选择“API 和服务”选项以及“已启用的 API 和服务”。

图片:显示了“启用 API”菜单的使用情况。

选择“启用 API 和服务”选项

显示“选择启用 API”菜单的图片。

在搜索框中输入“Maps JavaScript API”。

显示 API 搜索框的图片

选择匹配的结果。

显示“选择匹配的 API”框的图片

然后,点击相应 API 上的“启用”,将其添加到您的项目中(如果您之前使用过此项目,可能已完成此操作)。

显示“启用匹配的 API”框的图片

启用此功能后,您可以选择添加 API 密钥并对其进行限制,但现在将跳过此步骤。

再次使用左侧菜单选项,返回到“API 和服务”部分,然后选择为您创建的浏览器密钥。

显示限制 API 的图片。

将 Maps JavaScript API 添加到其中一项 API 限制中。

选择要过滤的 Maps API。

对于正式版应用中的密钥,您还需要限制托管应用的网域,现在使用在 Firebase 中为您创建的网域执行此操作。您还应在网域末尾添加 /*,以确保涵盖其下的所有路径。

要限制到的网域。

如需详细了解如何启用此功能,请参阅以下位置,详细了解如何限制 API 密钥。

https://developers.google.com/maps/api-security-best-practices#restricting-api-keys

7. 创建 reCAPTCHA 密钥

下一步是创建 reCAPTCHA 项目,以便为客户端和服务器提供证明和密钥。

前往 reCAPTCHA 网站 (https://www.google.com/recaptcha/),然后点击“开始使用”按钮。

显示 reCAPTCHA 使用入门的图片。

接下来,注册一个新网站,确保您输入了要限制的正确网域。

图片:注册 reCAPTCHA 网站。

如果您有多个 Google Cloud 项目,请确保您选择的是 Firebase 创建的那个项目。

这会创建两个密钥:一个您将输入到 Firebase 控制台中的密钥(此密钥绝不应放入任何可公开查看的网页或应用中),以及一个您将在 Web 应用中使用的网站密钥。

显示 reCAPTCHA 密钥页面的图片。

请让此页面保持打开状态,因为您需要用到它。点击“复制密钥”按钮,然后返回 Firebase 网站。

8. 向 Firebase 添加 reCAPTCHA

在 Firebase 管理控制台中,前往左侧菜单项。在构建菜单项下,选择 App Check。

显示托管 build 菜单的图片。

在注册应用之前,无法启用服务列表(之前向网站添加托管时已创建应用),如果您需要设置此项,请点击“开始”。

点击“应用”标签页,打开“Web 应用”,然后输入从 reCAPTCHA 网站复制的密钥,并点击“保存”。

图片:显示输入密钥

现在,reCAPTCHA 提供方旁边应该会显示一个绿色对勾标记。此 Web 应用现在可以使用 reCAPTCHA 来证明用户或网站是否正确调用了该服务。

绿色对勾表示 reCAPTCHA 已启用

在“API”标签页上,系统现在应显示 Google Maps Platform API 已处于有效状态,但未强制执行。

App Check 已启用但未强制执行。

您现在已将 reCAPTCHA 密钥与 Firebase 项目相关联,接下来可以向网页中添加代码,以将网站密钥与正确的提供方相匹配,以便与 Maps 应用搭配使用。

reCAPTCHA 会检查网站密钥是否与密钥匹配,匹配后会确认调用网页是否正确,然后 App Check 会提供一个令牌,供后续调用 Maps JavaScript API 时使用。如果没有此证明,系统不会提供令牌,并且无法验证请求。

9. 向网页添加验证并进行部署。

返回 Cloud 控制台,复制需要用于 Maps API 的 API 密钥。

您可以在控制台的侧边菜单中找到此信息,具体位于“API 和服务”侧边菜单下的“凭据”选项中。

显示“凭据”菜单的图片。

您可以在此处选择现有的浏览器密钥(不过如上所述,您也可以使用其他现有密钥或创建新密钥)。

显示“现有浏览器密钥”选项的图片。

点击“显示密钥”按钮,然后从显示的对话框窗口中复制密钥。

返回之前打开您创建的 HTML 页面的 Firebase Studio 项目。现在,您可以将 API 密钥添加到网页中,以便在网页包含 “YOUR_API_KEY”的情况下,使 Maps API 正常运行。

更新 API 密钥

重新运行该网页后,系统现在会显示不同的错误消息。

“不允许的引荐来源网址”错误消息

这意味着,您托管网页的开发网域不受允许(我们只添加了已部署的网域)。我们需要使用 Firebase 托管将此网站发布到正确的网域。如需了解更多详情,请访问以下页面:

使用 Firebase 托管进行部署

以及此视频

在 Project IDX 中更快地构建、测试和部署您的 Firebase Web 应用

“未启用结算功能”错误。

如需了解更多详情,请访问 Maps JavaScript API 网站,查看地图加载错误

如果您遇到 RefererNotAllowedMapError,可以通过将网页部署到正确的网域来解决此问题。

返回 Firebase Studio,然后点击“Firebase Studio”图标(此图标可能位于最左侧或最右侧,具体取决于您设置的选项),以打开托管选项。

显示 Firebase Studio 图标的图片。

在本 Codelab 中,您接下来需要“使用 Firebase 托管应用”,以将 Firebase 实例与 Studio 应用相关联。

使用 Firebase 托管选项。

然后,点击“对 Firebase 账号进行身份验证”以开始身份验证流程,这样您的账号就能在 Studio 中自动执行后端托管。

图片:显示“Authenticate Firebase”选项。

按照命令窗口中的说明授权部署。

图片:显示身份验证说明。

按照屏幕上的说明(包括打开新窗口),在系统要求时复制授权代码,然后将其粘贴到 Firebase Studio 中的命令窗口中。

显示 Firebase 授权代码的图片。

如需详细了解此流程,请访问以下页面:

https://firebase.google.com/docs/studio/deploy-app

完成此操作后,您可以点击“初始化 Firebase 托管”将项目与 Firebase 项目相关联。

选择“使用现有项目”,然后选择您在前面部分中创建的项目。接受其余默认设置(您的示例可能会因您在设置项目时选择的名称而异)。

Firebase 托管项目设置。

返回到资源管理器视图,然后将公共目录中创建的 index.html 文件替换为您之前在根目录中创建的文件。

显示托管文件结构的图片。

现在,您可以返回 Firebase Studio 边栏,并将网站部署到正式版。

显示“部署到生产环境”的图片。

这会在控制台中显示部署步骤。

显示部署步骤的图片。

通过显示的“托管网址”(此处显示为 https://my-app-check-project.web.app/,但您的项目会显示不同的网址)打开已部署的网站。

现在,应用会在网页上显示地图,因为 API 适用于所使用的网域。

显示托管 build 菜单的图片。

现在,您有了一个可正常运行的网页,其中包含对可与 API 密钥搭配使用的 API 类型以及 API 密钥可能用于的网域的限制。下一步是将访问权限锁定为仅限该网域。为此,您需要添加之前生成的 Firebase 脚本部分,以使用 App Check 保护网页。我们将在下一部分中完成此操作。

10. 安全页面

虽然当前网页可确保 API 密钥的安全性,但它不会添加证明步骤,以确保该密钥是由正确的应用和人员使用的。密钥仍可能会被恶意行为者窃取和使用。为了停止此操作,需要将 Firebase 配置、提供方和网站密钥添加到网页中,以便为客户端获取正确的令牌。

您还可以看到,对于 Maps API,用量是在 Firebase 中跟踪的。由于它未使用任何正确的令牌,因此会发出未经验证的请求。

所需的连接详细信息可从 Firebase 项目中获取。

从包含 Firebase 配置详细信息的控制台中获取 Firebase 详细信息。前往 Firebase 下的项目设置页面,然后在应用的 CDN 部分下,获取 CDN 设置的代码部分(最简单)。

在 Firebase 项目中,选择齿轮图标以显示项目设置。

显示 Firebase 项目设置的图片

系统随即会打开以下页面,其中包含“常规”部分中的详细信息(位于您的应用下方)。

Firebase 应用配置设置。

将此代码复制到包含地图且已托管的 Firebase Studio 页面 (public/index.html) 中。该文件将如下所示(包含您的详细信息,而不是此文件中的详细信息):

<!doctype html>
<html>

<head>
 <title>Secure Map</title>
 <style>
   #map {
     height: 100%;
   }

   html,
   body {
     height: 100%;
     margin: 0;
     padding: 0;
     font-family: Arial, Helvetica, sans-serif;
   }
 </style>
</head>

<body>
 <h3>App Check Security Demo</h3>
 <!--The div element for the map -->
 <div id="map"></div>
 <script>
   (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
     key: "YOUR_API_KEY",
     v: "weekly",
     // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
     // Add other bootstrap parameters as needed, using camel case.
   });
 </script>
 <script type="module">
   // Import the functions you need from the SDKs you need
   import { initializeApp } from "https://www.gstatic.com/firebasejs/12.2.1/firebase-app.js";

   const firebaseConfig = {
     apiKey: "YOUR_API_KEY",
     authDomain: "appcheck-map.firebaseapp.com",
     projectId: "appcheck-map",
     storageBucket: "appcheck-map.firebasestorage.app",
     messagingSenderId: "YOUR_SENDER_KEY",
     appId: "YOUR_APP_ID"
   };
    // Initialize Firebase
   const app = initializeApp(firebaseConfig);

   let map;
   async function initMap() {
     const { Map } = await google.maps.importLibrary("maps");
     map = new Map(document.getElementById("map"), {
       center: { lat: 51.5208, lng: -0.0977 },
       zoom: 17,
     });
   }
   initMap();
 </script>
</body>

</html>

现在,Firebase 已添加到我们的应用中,对 reCAPTCHA 库的调用使用您之前从 reCAPTCHA 网站获得的网站密钥(之前)。

显示 reCAPTCHA 网站密钥输入的图片。

如需详细了解如何添加这些版块,请访问以下 Google 地图文档页面:

https://developers.google.com/maps/documentation/javascript/maps-app-check

将 App Check 库添加到网页中,然后加载函数以使用 Firebase 配置初始化 App Check,并使用 ReCaptchaV3Provider 获取令牌。

首先,导入 App Check 库:

       import {
           getToken,
           initializeAppCheck,
           ReCaptchaV3Provider,
       } from "https://www.gstatic.com/firebasejs/12.2.1/firebase-app-check.js";

接下来,您需要添加代码,以使用网站令牌通过 Firebase 配置和 reCAPTCHA 提供程序初始化 App Check。

       // Get App Check Token
       const appCheck = initializeAppCheck(app, {
           provider: new ReCaptchaV3Provider('<INSERT SITE KEY>'),
           isTokenAutoRefreshEnabled: true,
       });

最后,使用 Maps Core 库的设置函数将函数附加到地图控件,以获取令牌。这样一来,地图控件就会根据令牌的有效时长按需发出令牌请求。

       const { Settings } = await google.maps.importLibrary('core');
     Settings.getInstance().fetchAppCheckToken = () =>
           getToken(appCheck, /* forceRefresh = */ false);

完整的文件如下所示:

<!doctype html>
<html>

<head>
 <title>Secure Map</title>
 <style>
   #map {
     height: 100%;
   }

   html,
   body {
     height: 100%;
     margin: 0;
     padding: 0;
     font-family: Arial, Helvetica, sans-serif;
   }
 </style>
</head>

<body>
 <h3>App Check Security Demo</h3>
 <!--The div element for the map -->
 <div id="map"></div>
 <script>
   (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
     key: "YOUR_API_KEY",
     v: "weekly",
     // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
     // Add other bootstrap parameters as needed, using camel case.
   });
 </script>
 <script type="module">
   import { initializeApp } from "https://www.gstatic.com/firebasejs/12.2.1/firebase-app.js";

   import {
     getToken,
     initializeAppCheck,
     ReCaptchaV3Provider,
   } from "https://www.gstatic.com/firebasejs/12.2.1/firebase-app-check.js";

   const firebaseConfig = {
     apiKey: "YOUR_API_KEY",
     authDomain: "appcheck-map.firebaseapp.com",
     projectId: "appcheck-map",
     storageBucket: "appcheck-map.firebasestorage.app",
     messagingSenderId: "YOUR_SENDER_KEY",
     appId: "YOUR_APP_ID"
   };

   // Initialize Firebase
   const app = initializeApp(firebaseConfig);

   // Get App Check Token
   const appCheck = initializeAppCheck(app, {
     provider: new ReCaptchaV3Provider('<INSERT SITE KEY>'),
     isTokenAutoRefreshEnabled: true,
   });

   let map;
   async function initMap() {
     const { Map } = await google.maps.importLibrary("maps");

     const { Settings } = await google.maps.importLibrary('core');
     Settings.getInstance().fetchAppCheckToken = () =>
       getToken(appCheck, /* forceRefresh = */ false);

     map = new Map(document.getElementById("map"), {
       center: { lat: 51.5208, lng: -0.0977 },
       zoom: 17,
     });
   }
   initMap();
 </script>
</body>

</html>

使用 Firebase Studio 将此内容部署到 Firebase 网站,然后运行该网页。

11. 强制执行监控

现在,页面已设置完毕,当它运行时,您可以看到它正在被检查。返回 Firebase 控制台,然后再次打开 App Check 部分。App Check 现在应该正在监控 Maps JavaScript API。

正在检查监控功能是否已开启。

打开窗口后,您现在会看到客户端正在发出请求,并且证明正在正常运行(图表上显示深蓝色的“已验证”请求)。在验证完成之前,其他请求会在开发阶段显示调用。

显示已验证请求的图表。

现在,客户端可以正常运行,接下来可以在网站上启用强制执行,以确保 API 密钥无法从无效的客户端应用中使用。点击“强制执行”按钮即可开始强制执行。

显示“强制执行”按钮的图片。

点击此按钮后,系统会显示一个大型警告标志,表明此操作会锁定您的应用。在实际应用中,只有在您确定所有客户都拥有正确的密钥且密钥有效时,您才会执行此操作,否则您的用户可能无法访问该网站。

显示违规处置对话框的图片。

此外,强制执行此政策也可能需要一些时间。屏幕上会显示相关提示,如果您立即测试强制执行情况,系统可能还没有时间传播。

15 分钟后强制执行。

在请求网页时,您应该能够看到它像以前一样正常运行,网站实际上没有任何变化。

现在,随着时间的推移,您应该会在控制台中看到已验证的请求数量增加,如下所示:

图表:显示验证请求数量增加。

您可以返回到 Codelab 中的原始示例,创建一个没有应用检查功能的新网页,以测试该功能是否正常运行。将此网页命名为 nocheck.html,并将其放置在与 index.html 相同的公共文件夹中。

<!doctype html>
<html>

<head>
 <title>Secure Map</title>
 <style>
   #map {
     height: 100%;
   }

   html,
   body {
     height: 100%;
     margin: 0;
     padding: 0;
     font-family: Arial, Helvetica, sans-serif;
   }
 </style>
</head>

<body>
 <h3>App Check Security Demo</h3>
 <!--The div element for the map -->
 <div id="map"></div>
 <script>
   (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
     key: "YOUR_API_KEY",
     v: "weekly",
     // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
     // Add other bootstrap parameters as needed, using camel case.
   });
 </script>
 <script>
   let map;
   async function initMap() {
     const { Map } = await google.maps.importLibrary("maps");
     map = new Map(document.getElementById("map"), {
       center: { lat: 51.5208, lng: -0.0977 },
       zoom: 17,
     });
   }
   initMap();
 </script>
</body>

</html>

完成此操作并输入正确的 API 密钥后,当您请求网页(使用 yourdomain/nocheck.html)时,应该会看到以下灰色错误框。

“出了点问题”错误。

检查控制台,您应该会看到类似以下内容的错误消息:

“应用检查无效”错误消息

应用检查已成功阻止了网页上地图的请求,因为该网页不再获取强制执行网站的应用检查令牌。

12. 恭喜!

恭喜!您已成功在网站上启用 App Check!

显示正常运行的应用的页面

您已成功构建一个应用,该应用使用 Firebase App Check 来确保请求来自有效的网域和用户。

要点回顾

  • 如何使用 Firebase Studio 托管和部署网页。
  • 如何使用 Cloud 控制台启用和保护 Google Maps Platform API。
  • 如何使用 reCAPTURE 生成可用于证明调用的密钥。
  • 如何使用 Firebase App Check 并将其集成到 Maps JavaScript API 中。
  • 了解如何使用 Firebase Studio 强制执行和监控对受保护网站的调用。

后续操作

  • 查看适用于 Google Maps JavaScript API 的 App Check 的文档
  • 详细了解 Firebase 中的 App Check。
  • 不妨尝试另一个包含 App Check 和 Google Maps Places API 的 Codelab。
  • 详细了解 reCAPTCHA