首页 > 解决方案 > Firestore 安全规则:如何限制使用 get()?

问题描述

所以我有一个查询(失败)。它的内容如下:“作为我的用户,我可以为一个组织列出我所属的所有业务”。

fs
    .collection('businesses')
    .where('organizationUid', isEqualTo: 'some-organization-id')
    .get();

以及保护它的安全规则(它的要点):

match /businesses/{businessId} {
  function isStaffOrHigher() {
    return get(/databases/$(database)/documents/businesses/$(businessId)/users/$(request.auth.uid)).data.role >= 50;
  }

  allow read: if isStaffOrHigher();

  match /orders/{orderId} {
    allow read, write: if isStaffOrHigher();
  }

  match /users/{userId} {
    allow read: if request.auth.uid == userId || isStaffOrHigher();
  }
}

基本上,它会在用户文档(由该企业拥有)中查找用户的角色。这种类型的规则(使用get()运算符)适用于 的子集合(orders例如,查询没有问题){businessId},但不适用于尝试列出企业的查询。

现在我知道这organizationUid是一个有效的约束,但是已经阅读了Rules are not filters,我可以理解为什么 Firestore 无法在不读取大量数据的情况下验证此声明。

问题只是,那我该如何解决呢?Firestore 如何正确验证子集合的约束?

标签: google-cloud-firestorefirebase-security

解决方案


安全规则不会做你想做的事,因为它需要为查询匹配的每个文档读取另一个文档。规则无法提前知道这些文档将是什么,因为businessId路径中有变量 ( )。如果此查询将产生数百万个企业集合的文档,您可以看到从 /businesses/$(businessId)/users/$(request.auth .uid) 来确定是否应该允许拒绝整个查询。

规则必须非常快速地运行才能以 Firestore 需要扩展的方式进行扩展。规则不能作为过滤器的限制是可扩展性要求的一部分。这也是get()每个规则评估读取 10 个文档的总体限制的原因。

从规则的角度来看,这里没有解决方法,除了执行多个查询,每个查询都在每个集合的规则范围内,并在您的客户端应用程序中合并结果。


推荐阅读