You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firestore子集合列表权限问题:无法限制groups子集合列表访问

问题分析与解决方案

核心问题

你的权限问题主要由路径拼写错误和集合查询的规则限制导致:

  1. 路径拼写不匹配:规则中多处集合名称与实际路径不符,导致权限验证逻辑根本未触发:
    • 实际组织集合路径是/organizations,但规则写为/organization(单数)
    • 实际用户集合路径是/users,但规则中读取用户文档时写为/user(单数)
    • 实际群组子集合路径是/organizations/{orgId}/groups,但规则写为/group(单数)
  2. 集合查询的性能限制:即使修正路径,使用get()读取用户文档的规则在集合查询时会被Firestore拒绝——Firestore无法为集合中的每个文档都执行一次get()操作(存在性能瓶颈)。

修正后的安全规则

首先修正所有路径错误,同时优化规则逻辑,避免重复读取用户文档:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // 封装用户组织ID的获取逻辑,避免重复调用get()
    function getUserOrganization() {
      return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.organization_id;
    }

    // 匹配实际的organizations集合
    match /organizations/{organizationId} {
      allow create: if request.auth != null;
      allow read, update: if getUserOrganization() == organizationId;

      // 匹配实际的groups子集合
      match /groups/{groupId} {
        allow read, write: if getUserOrganization() == organizationId;
      }
    }

    match /users/{userId} {
      allow create, read: if request.auth != null;
      allow update: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.is_global_admin == true;
    }
  }
}

进一步优化(解决集合查询性能问题)

上述规则虽能解决路径问题,但集合查询仍可能存在性能限制。推荐将用户的organization_id存入Firebase Auth的自定义声明中,这样无需读取用户文档即可验证权限:

1. 设置自定义声明(后端执行,如Cloud Functions)

const admin = require('firebase-admin');
admin.initializeApp();

// 用户登录或组织变更时执行
async function setUserOrganizationClaim(uid, organizationId) {
  await admin.auth().setCustomUserClaims(uid, {
    organization_id: organizationId
  });
}

2. 更新安全规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // 直接从Auth自定义声明获取组织ID,无需读取用户文档
    function getUserOrganization() {
      return request.auth.token.organization_id;
    }

    match /organizations/{organizationId} {
      allow create: if request.auth != null;
      allow read, update: if getUserOrganization() == organizationId;

      match /groups/{groupId} {
        allow read, write: if getUserOrganization() == organizationId;
      }
    }

    match /users/{userId} {
      allow create, read: if request.auth != null;
      allow update: if request.auth.token.is_global_admin == true;
    }
  }
}

验证查询代码

你的查询代码无需修改,但需确保传入的org参数是用户所属的组织ID——规则会自动拦截不属于用户组织的查询请求。

内容的提问来源于stack exchange,提问作者Chris Edgington

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 06:55:12