【问题标题】:Firestore security rule - {wildcard} is neither null or not null when getting collectionFirestore 安全规则 - 获取集合时 {wildcard} 既不是 null 也不是 null
【发布时间】:2019-04-09 09:20:15
【问题描述】:

我已经在我的 firestore 上设置了一个读取规则,它在通过 id 对单个文档执行获取时工作正常,但在获取集合时失败并出现 FirebaseError: Missing or insufficient permissions. 错误。

查询集合时好像是路径中的通配符没有正确绑定。我已经归结为一个最小的示例,从逻辑上讲,我认为它不应该使许可失败,但确实如此。 如下:

数据(格式化,但当然是在集合/文档中组织):

"items": {                   // collection "items"
   "item1" : {               // document "item1"
      "name": "first item"   // just dome dummy data
   }
}

规则:

service cloud.firestore {
    match /databases/{database}/documents {
        match /items/{itemId} {
            allow read: if itemId != null;
        }
    }
}

我用来访问数据库的代码(打字稿)

// This line works fine, returns the document
firebase.firestore().collection("/items").doc("item1").get()

// This line gets a "FirebaseError: Missing or insufficient permissions." error
firebase.firestore().collection("/items").get()

我已尝试将规则更改为

allow read: if itemId != null || itemId == null;

这在逻辑上应该总是正确的。但是,结果仍然相同,这让我相信绑定到 itemId 通配符时存在一些问题。

作为健全性检查,我还将规则更改为

allow read: if true;

现在集合上的get() 和文档都可以正常工作(如预期的那样),没有任何权限错误。

所以我在这里遗漏了什么,或者这是 Firestore 中的错误???

【问题讨论】:

  • 您希望此规则何时会明确拒绝访问?在我看来,您没有明确的拒绝案例,这意味着您的规则一开始就没有太多目的。
  • 当然我的域比这更复杂,我只是将问题归结为最少的代码集来重现问题。主要问题是绑定通配符/文档 id 的问题使我无法制定任何有意义的访问规则。而且我在文档中没有看到通配符仅适用于获取单个文档而不是集合查询。
  • 我认为最好(出于这个问题的目的)用一个不符合您期望的真实规则来展示您在此处实际尝试完成的工作。如果你的规则没有明确的目的,就很难说你是否正确地考虑了这个问题。
  • 好点,应该这样做。只是想让它变得简单,因为我认为我已经缩小到问题所在,并且不想让问题变得混乱

标签: firebase google-cloud-firestore firebase-security


【解决方案1】:

首先,你的规则对我来说没有意义。检查文档ID是否不是null的目的是什么?一个有效的文档不可能有 null 文档 ID。


来自Queries and security rules

在编写查询以检索文档时,请记住安全性 规则不是过滤器——查询是全有或全无。为了节省您的时间和 资源,Cloud Firestore 根据其潜力评估查询 结果集而不是您所有的实际字段值 文件。如果查询可能会返回文档 客户端没有读取权限,整个请求失败。

在您的情况下,firestore 可能认为您的查询可能会返回您可能无权阅读的文档。它以某种方式认为某些文档可能具有null 文档ID,从而拒绝了整个请求。

当您将规则更改为 allow read: if true; 时,它会起作用,因为 Firestore 对其进行了评估并且知道该规则肯定会针对每个文档通过,因此授予您读取权限。

【讨论】:

    【解决方案2】:

    您提出的规则不起作用,因为(因为它目前已实现),通配符变量对于列表(查询)类型请求具有未定义的值(但不适用于获取类型请求,因为文档 ID 是当然直接来自客户)。查询可能匹配多个文档,而您的查询未指定文档 ID,因此无法在规则中使用。

    如果您期望某个规则根据每个文档来决定它是否属于查询结果,那也永远不会奏效。这是因为规则不是过滤器。所有过滤器都必须来自客户端。如果给定过滤器可能存在任何文档将被规则拒绝,则整个请求将被拒绝。 (在请求时实际检查所有文档是不可扩展的 - 这可能非常慢)。

    换句话说,如果您想影响查询,请不要使用通配符变量。只使用可以匹配的文档的属性,并确保客户端指定了所有相关的过滤器。

    【讨论】:

    • 可以肯定地说,“{wildcard} 只能用于将单个文档 id 传递到 get() 的查询的规则中”?例如:db.collection("cities").doc("SF").get(); 可以工作,db.collection("cities").where("capital", "==", true).get() 不行?
    【解决方案3】:

    如果您不想同时读取多个文档

    这就是规则

    service cloud.firestore {
        match /databases/{database}/documents {
            match /items/{itemId} {
                allow list: if false;
                allow get: if true ;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-10-15
      • 1970-01-01
      • 2015-09-16
      • 2012-04-11
      • 2018-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多