Google 致力于为黑人社区推动种族平等。查看具体举措

管理和部署 Firebase 安全规则

使用 Firebase CLI

使用 Firebase CLI 修改和部署规则。使用 CLI,您可以借助应用代码将规则保持在版本控制之下,并将规则部署为现有部署过程的一部分。

生成配置文件

使用 Firebase CLI 配置 Firebase 项目时,您可在项目目录中创建 .rules 配置文件。使用以下命令开始配置 Firebase 项目:

Cloud Firestore

// Set up Firestore in your project directory, creates a .rules file
firebase init firestore

Realtime Database

// Set up Realtime Database in your project directory, creates a .rules file
firebase init database

Cloud Storage

// Set up Storage in your project directory, creates a .rules file
firebase init storage

修改和更新您的规则

直接在 .rules 配置文件中修改规则。确保您在 Firebase CLI 中进行的所有修改都体现在 Firebase 控制台中,或者您始终使用 Firebase 控制台或 Firebase CLI 进行更新。否则,您可能会覆盖在 Firebase 控制台中所做的所有更新。

测试您的更新

使用 Firebase 模拟器在本地测试您的更新,并确认您的应用规则显示您想要的行为。

部署您的更新

您更新并测试了规则之后,就可以将它们部署到生产环境中。 使用以下命令,可以选择单独部署规则,或者将其作为正常部署过程的一部分进行部署。

Cloud Firestore

// Deploy your .rules file
firebase deploy --only firestore:rules

Realtime Database

// Deploy your .rules file
firebase deploy --only database

Cloud Storage

// Deploy your .rules file
firebase deploy --only storage

使用 Firebase 控制台

您还可以从 Firebase 控制台修改和部署规则。

修改和更新您的规则

  1. 打开 Firebase 控制台,然后选择您的项目。
  2. 然后从产品导航中选择 Realtime DatabaseCloud FirestoreStorage,再点击规则以导航到规则编辑器。
  3. 直接在编辑器中修改规则。

测试您的更新

您可以使用规则模拟器直接在 Firebase 控制台中测试规则行为。在规则编辑器中打开模拟器屏幕,修改设置并点击运行。在编辑器顶部查找确认消息。

部署您的更新

如果您的更新如您所愿,对此您感到很满意,请点击发布

使用 Admin SDK

您可以使用 Node.js 版 Admin SDK 以编程方式创建、管理和部署安全规则。通过以编程方式访问,您可以执行以下操作:

  • 实现自定义工具、脚本、信息中心和 CI/CD 流水线以管理规则。
  • 更轻松地管理多个 Firebase 项目的规则。

以编程方式更新规则时,请务必避免意外更改应用的访问权限控制。在编写 Admin SDK 代码时,请特别注意安全问题,尤其是在更新或部署规则时。

另一个需要注意的重要事项是,Firebase 安全规则需要几分钟的时间才能完成部署。使用 Admin SDK 部署规则时,请务必避免出现争用的情况,即应用立即依赖于部署尚未完成的规则。如果您的用例需要频繁更新访问权限控制规则,请考虑使用 Cloud Firestore 解决方案,该方案可有效避免频繁更新时出现争用的情况。

另请注意以下限制:

  • 规则在序列化后必须小于 64KiB 的 UTF-8 编码文本。
  • 一个项目最多只能有 2500 个已部署的规则集。达到上限后,您必须先删除一些旧规则集,然后才能创建新规则集。

创建和部署 Cloud Storage 或 Cloud Firestore 规则集

使用 Admin SDK 管理安全规则的典型工作流程包括三个独立的步骤:

  1. 创建规则文件(可选)
  2. 创建规则集
  3. 发布或部署新规则集

SDK 提供了一种方法,可将这几个步骤合并到针对 Cloud Storage 和 Cloud Firestore 安全规则的单个 API 调用中。例如:

    const source = `service cloud.firestore {
      match /databases/{database}/documents {
        match /carts/{cartID} {
          allow create: if request.auth != null && request.auth.uid == request.resource.data.ownerUID;
          allow read, update, delete: if request.auth != null && request.auth.uid == resource.data.ownerUID;
        }
      }
    }`;
    // Alternatively, load rules from a file
    // const fs = require('fs');
    // const source = fs.readFileSync('path/to/firestore.rules', 'utf8');

    await admin.securityRules().releaseFirestoreRulesetFromSource(source);

此模式同样适用于具有 releaseFirestoreRulesetFromSource() 的 Cloud Storage 规则。

或者,您可以将规则文件创建为内存对象,创建规则集,并单独部署此规则集以进一步控制这些事件。 例如:

    const rf = admin.securityRules().createRulesFileFromSource('firestore.rules', source);
    const rs = await admin.securityRules().createRuleset(rf);
    await admin.securityRules().releaseFirestoreRuleset(rs);

更新实时数据库规则集

如需使用 Admin SDK 更新实时数据库规则集,请使用 admin.databasegetRules()setRules() 方法。您可以以 JSON 格式检索规则集,或者以包含注释的字符串形式检索规则集。

如需更新规则集,请使用以下语句:

    const source = `{
      "rules": {
        "scores": {
          ".indexOn": "score"
            "$uid": {
            ".read": "$uid == auth.uid",
            ".write": "$uid == auth.uid"
          }
        }
      }
    }`;
    await admin.database().setRules(source);

管理规则集

为便于管理大型规则集,Admin SDK 允许您使用 admin.securityRules().listRulesetMetadata 列出所有现有规则。例如:

    const allRulesets = [];
    let pageToken = null;
    while (true) {
      const result = await admin.securityRules().listRulesetMetadata(pageToken: pageToken);
      allRulesets.push(...result.rulesets);
      pageToken = result.nextPageToken;
      if (!pageToken) {
        break;
      }
    }

对于随着时间推移达到 2500 条规则上限的超大型规则集,您可以创建逻辑来删除固定时间周期内最旧的规则。例如,如需删除部署时间超过 30 天的所有规则集,请使用以下语句:

    const thirtyDays = new Date(Date.now() - THIRTY_DAYS_IN_MILLIS);
    const promises = [];
    allRulesets.forEach((rs) => {
      if (new Date(rs.crateTime) < thirtyDays) {
        promises.push(admin.securityRules().deleteRuleset(rs.name));
      }
    });
    await Promise.all(promises);
    console.log(`Deleted ${promises.length} rulesets.`);