我已经在我的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;
}
}
}
我用来访问数据库的代码(typescript)
// 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中的一个bug?
您提议的规则不起作用,因为(因为它是当前实现的),通配符变量具有列表(查询)类型请求的未定义值(但不是get类型请求,因为文档ID当然是直接来的来自客户)。查询可能与多个文档匹配,并且您的查询未指定文档ID,因此无法在规则中使用。
如果您希望规则在每个文档的基础上决定它是否属于查询结果,那么它也永远不会起作用。这是因为规则不是过滤器。所有过滤器都必须来自客户端。如果规则拒绝给定过滤器可能存在的任何文档,则拒绝整个请求。 (在请求时实际检查所有文档是不可扩展的 - 这可能非常慢)。
换句话说,如果要影响查询,请不要使用通配符变量。仅使用可匹配的文档的属性,并确保客户端指定所有相关的过滤器。
首先,你的规则对我没有意义。检查文档ID是不是null
的目的是什么?有效文档无法拥有null
文档ID。
在编写查询以检索文档时,请记住安全规则不是过滤器 - 查询是全部或全部。为了节省您的时间和资源,Cloud Firestore会针对其潜在结果集评估查询,而不是针对所有文档的实际字段值。如果查询可能返回客户端无权读取的文档,则整个请求将失败。
在您的情况下,firestore可能认为您的查询可能会返回您可能无权阅读的文档。它以某种方式认为某些文档可能具有null
文档ID,从而拒绝整个请求。
当您将规则更改为allow read: if true;
时,它可以正常运行,因为Firestore会对其进行评估,并且知道该规则肯定会为每个文档传递,因此授予您读取权限。