Firebase Data Connect Admin SDK 让您可以从 受信任的环境(例如 Cloud Functions、自定义后端或您自己的 工作站)调用查询和变更。与为客户端应用生成 SDK 的方式非常相似,您 可以在设计部署到 Data Connect 服务的架构、查询 和变更时,并行生成自定义 Admin SDK。然后,您可以将此 SDK 中的方法集成到后端逻辑或管理脚本中。
正如我们在其他地方提到的,请务必注意,Data Connect查询 和变更不会在请求时由客户端提交。 相反,部署后,Data Connect 操作会像 Cloud Functions 一样存储在服务器上。这意味着,每当您部署对查询和变更的更改时,还需要重新生成 Admin SDK 并重新部署依赖于这些 SDK 的任何服务。
准备工作
- 了解如何设计 Data Connect 架构、查询和变更。 在典型的工作流中,您将与应用代码并行开发这些内容,包括使用 Admin SDK 的任何服务。
在您计划调用生成的 Admin SDK 的任何位置,将 Node.js 版 Admin SDK 作为依赖项 包含在内。
生成 Admin SDK
创建您的 Data Connect 架构、查询和变更后,您可以 生成相应的 Admin SDK:
打开或创建
connector.yaml文件,并添加adminNodeSdk定义:connectorId: default generate: adminNodeSdk: outputDir: ../../dataconnect-generated/admin-generated package: "@dataconnect/admin-generated" packageJsonDir: ../..connector.yaml文件通常与包含查询和变更定义的 GraphQL (.gql) 文件位于同一目录中。如果您已生成客户端 SDK,则此文件已创建。生成 SDK。
如果您安装了 Data Connect VS Code 扩展程序,它将始终使生成的 SDK 保持最新状态。
否则,请使用 Firebase CLI:
firebase dataconnect:sdk:generate或者,如需在更新
gql文件时自动重新生成 SDK,请执行以下操作:firebase dataconnect:sdk:generate --watch
从 Admin SDK 执行操作
生成的 Admin SDK 包含与 gql 定义对应的接口和函数,您可以使用这些接口和函数对数据库执行操作。例如,假设您为歌曲数据库生成了一个 SDK,以及一个查询 getSongs:
import { initializeApp } from "firebase-admin/app";
import { getSongs } from "@dataconnect/admin-generated";
const adminApp = initializeApp();
const songs = await getSongs(
{ limit: 4 },
{ impersonate: { unauthenticated: true } }
);
或者,如需指定连接器配置,请执行以下操作:
import { initializeApp } from "firebase-admin/app";
import { getDataConnect } from "firebase-admin/data-connect";
import {
connectorConfig,
getSongs,
} from "@dataconnect/admin-generated";
const adminApp = initializeApp();
const adminDc = getDataConnect(connectorConfig);
const songs = await getSongs(
adminDc,
{ limit: 4 },
{ impersonate: { unauthenticated: true } }
);
模拟未经身份验证的用户
Admin SDK 旨在从受信任的环境运行,因此可以不受限制地访问您的数据库。
使用 Admin SDK 运行公共操作时,您应避免使用完整管理员权限运行该操作(遵循最低权限原则)。相反,您应以模拟用户(请参阅下一部分)或模拟未经身份验证的用户的身份运行该操作。
未经身份验证的用户只能运行标记为 PUBLIC 的操作。
在上面的示例中,getSongs 查询以未经身份验证的用户的身份执行。
模拟用户
您还可以通过在 impersonate 选项中传递部分或
全部 Firebase Authentication 令牌来代表特定用户执行操作;您
至少必须在 sub 声明中指定用户的用户 ID。(此值与您可以在 Data Connect GraphQL 操作中引用的
auth.uid 服务器值
相同。)
当您模拟用户时,只有在您提供的用户数据通过 GraphQL 定义中指定的身份验证检查后,操作才会成功。
如果您从公开可访问的端点调用生成的 SDK,则至关重要的是,该端点需要身份验证,并且您需要在模拟用户之前验证身份验证令牌的完整性。
使用可调用的 Cloud Functions 时,系统会 自动验证身份验证令牌,您可以按以下示例所示的方式使用它:
import { HttpsError, onCall } from "firebase-functions/https";
export const callableExample = onCall(async (req) => {
const authClaims = req.auth?.token;
if (!authClaims) {
throw new HttpsError("unauthenticated", "Unauthorized");
}
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
// ...
});
否则,请使用 Admin SDK's verifyIdToken 方法来验证和解码
身份验证令牌。例如,假设您的端点实现为
纯 HTTP 函数,并且您已使用 authorization 标头将 Firebase Authentication 令牌
传递给您的端点(这是标准做法):
import { getAuth } from "firebase-admin/auth";
import { onRequest } from "firebase-functions/https";
const auth = getAuth();
export const httpExample = onRequest(async (req, res) => {
const token = req.header("authorization")?.replace(/^bearer\s+/i, "");
if (!token) {
res.sendStatus(401);
return;
}
let authClaims;
try {
authClaims = await auth.verifyIdToken(token);
} catch {
res.sendStatus(401);
return;
}
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
// ...
});
只有在从安全且非公开可访问的环境执行真正的管理任务(例如数据迁移)时,您才应指定并非源自可验证来源的用户 ID:
// Never do this if end users can initiate execution of the code!
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
以不受限制的访问权限运行
如果您要执行需要管理员级权限的操作,请从调用中省略 impersonate 参数:
await upsertSong(adminDc, {
title: songTitle_one,
instrumentsUsed: [Instrument.VOCAL],
});
以这种方式调用的操作可以完全访问数据库。如果您有仅用于管理目的的查询或变更,则应使用 @auth(level: NO_ACCESS) 指令定义它们。这样做可确保只有管理员级调用方才能执行这些操作。