为什么使用get()的Firestore安全规则不起作用,而使用resource.data的另一个规则却起作用? [英] Why does a Firestore security rule using get() not work while another rule using resource.data works?
问题描述
为了适应Cloud Firestore,我一直在研究聊天应用程序.
下面是其数据库的结构.
I've been working on a chat app in order to get used to Cloud Firestore.
Below is the structure of its database.
rooms
├ xxxxxx
│ ├ messages
│ │ ├ xxxxxx
│ │ └ xxxxxx
│ └ private
│ └ allowed - members [xxxxxxxx, xxxxxxxx]
└ xxxxxx
├ messages
│ ├ xxxxxx
│ └ xxxxxx
└ private
└ allowed - members [xxxxxxxx, xxxxxxxx]
每个聊天室文档下的 private
子集合都有一个单独的文档,其ID为 allowed
. allowed
具有 members
,这是一个数组字段,其中包含允许使用聊天室的用户的ID.
The private
subcollection under each chat room document has a single document with allowed
as its ID.
allowed
has members
, which is an array field holding IDs of users allowed to use the chat room.
要获取特定的聊天室,我首先要做的是获取 allowed
文档,如下所示:
What I have to do first to fetch a particular chat room is to get the allowed
document, as follows:
db.collectionGroup('private')
.where('members', 'array-contains', userId)
.get()
.then(...)
我已经在 private
上创建了用于集合组查询的索引,因此上述代码可以正常工作.
I've already created an index on private
for collection group queries, so the above code works.
但是,如果我添加以下安全规则,它将失败,并显示错误消息未捕获(承诺)FirebaseError:缺少权限或权限不足."
However, if I add the following security rule, it fails with the error message of 'Uncaught (in promise) FirebaseError: Missing or insufficient permissions.'
match /{path=**}/private/{document} {
allow read: if request.auth.uid
in get(/databases/$(database)/documents/$(path)/private/$(document)).data.members;
}
此规则用于禁止用户(如果不是会议室成员)禁止访问 allowed
.
没有 .where(...)
的查询会导致相同的错误.
This rule is for forbidding a user from accessing allowed
if not a member of the room.
A query without .where(...)
results in the same error.
另一方面,以下规则可以正常工作.
On the other hand, the rule below works as expected.
match /{path=**}/private/{document} {
allow read: if request.auth.uid in resource.data.members;
}
我知道这条规则到目前为止要好得多,所以我一定会使用它,但是我仍然想知道为什么以前的规则不起作用.
有人可以澄清原因吗?
I know this rule is by far better, so I'll definitely use it, but I still wonder why the previous rule didn't work.
Would anyone clarify the cause please?
这可能以任何方式相关吗?
Is this possibly related in any way?
推荐答案
您的安全规则是为collectionGroup /{path = **}/private
编写的,这是一回事-不论其在哪里,书面"都适用于任何名为私有"的集合.另外,您尝试使用变量 $(rule)
,该变量没有定义.
Your security rule was written for a collectionGroup /{path=**}/private
, for one thing - this rule, as written, applies to any collection named "private", regardless of where it is. Also, you try to use the variable $(rule)
, which I see no definition for.
安全规则仅适用于匹配查询-您必须确保查询 explicity 不会导致不允许的文档. IF 查询可能生成不允许的文档(即,由安全规则指定),然后将拒绝整个查询-不只是不允许的文档.安全规则是全有还是全无-这就是它们可以扩展的原因.
Security rules only work with matching queries - you have to make sure your query explicity cannot result in a un-allowed document. IF the query could result in an un-allowed document (i.e. as specified by the security rule), then the ENTIRE query will be rejected - not just the un-allowed document. Security rules are all-or-nothing - that's why they scale.
这篇关于为什么使用get()的Firestore安全规则不起作用,而使用resource.data的另一个规则却起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!