为什么使用get()的Firestore安全规则不起作用,而使用resource.data的另一个规则却起作用? [英] Why does a Firestore security rule using get() not work while another rule using resource.data works?

查看:46
本文介绍了为什么使用get()的Firestore安全规则不起作用,而使用resource.data的另一个规则却起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了适应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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆