【问题标题】:Security rules for large groups in firestoreFirestore 中大型组的安全规则
【发布时间】:2019-12-30 11:16:40
【问题描述】:

短版

我正在使用 firestore 构建一个应用程序,用户可以在其中创建课程、向这些课程添加资源,然后让其他用户注册他们的课程,这将使他们能够访问其所有资源。 我正在努力设置安全规则,以便只有课程组织者或课程成员才能访问资源。 我的主要问题是允许用户列出他们注册的课程中的所有资源,因为列表请求不允许在安全规则中进行查询,我需要检查该用户是否是该课程的成员。 让数百(或可能数千)课程成员轻松列出所有课程资源,同时确保非成员无法访问它的最佳方法是什么?

docs 的限制部分中,它特别提到将角色移动到大型或复杂组的单独集合中,但这样做将需要安全规则执行查询以检查访问权限,这对于列表请求是不可能的。


完整版

我正在创建一个客户端直接访问 firestore 的原型 Web 应用程序。消除对后端处理简单数据访问的需求令人耳目一新,但我现在真的很难为我的用例制定正确的数据结构和方法,尤其是在实施适当的安全规则方面。

我曾广泛使用关系数据库,但对 nosql 数据库和 firestore 还是很陌生,特别是没有帮助。

概念

我的应用程序中的主要集合是用户、课程和资源。 用户可以创建他们创建学习资源的课程,然后其他用户可以注册这些课程,因此可以访问其中的所有资源。 由于某些课程只会被邀请,因此用户无法访问他们不是其成员的课程的资源。

主要要求是:

  • 课程组织者需要对其课程和资源的完全读写权限。
  • 课程成员需要对其课程和资源的完全阅读权限。
  • 组织者和成员都需要能够轻松列出他们的所有课程,并为每门课程列出他们的所有资源。
  • 组织者和成员不应检索不属于他们的课程或资源的相关信息。

我的方法

首先我的方法是大量利用子集合。 从组织者的角度来看,用户的课程有资源,所以我就是这样建模的。

用户 -> 课程 -> 资源

组织者的安全规则在这里也非常简单,因为用户 ID 是文档路径的一部分,它可以通过可用的用户 uid 轻松检查(感谢 firebase auth)。

match /users/{userId}/courses/{courseId}/resources/{resourceId} {
    allow read, write, update, delete: if (request.auth.uid == userId) 
}

但事实证明,授予成员只读访问权限有点困难。我需要合适的地方来存储该映射。 我最终尝试使用用户子集来存储它,因此可以通过以下方式查找课程成员资格: /users/{userId}/course_memberships/{courseId}

理论上我可以编写一个安全规则来授予对课程和资源的读取权限,如下所示:

match /users/{userId}/courses/{courseId}/resources/{resourceId} {
    allow read: if exists(/databases/$(database)/documents/users/$(request.auth.uid)/course_memberships/${courseId})
}

但这仅在检索单个文档时有效,列表请求不会评估安全规则中的查询,因此此设置不允许课程成员查看给定课程中所有资源的列表。

我无法弄清楚这里的正确方法是什么,我看到的唯一选项是:

  1. 为每个成员创建一个单独的集合层次结构,其中包含他们的所有课程和所有资源,包括用于列出其资源的关键信息,并使用云功能同步这些信息。我知道 nosql 是关于存储非规范化的数据,但这感觉像是很多额外的数据,特别是当它只是安全规则所必需的时候。

  2. 将每个成员的 uid 添加到每个资源的数组中(可以 每个数以千计),这也感觉像很多额外的数据,它会 将这些 id 暴露给所有其他似乎错误的成员。

这里有没有更好的方法,还是 firestore 不太适合这种类型的问题?

希望这个问题尚未得到解答,我进行了搜索,但找不到涵盖完全相同场景的内容。

【问题讨论】:

  • 你是怎么解决的?我有同样的问题:(

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


【解决方案1】:

read 规则可以分为getlist,后者可以应用于查询。 示例:

允许列表:if [条件];

More information can be found here.

【讨论】:

  • 谢谢,但据我了解,在这种情况下我的问题是,对于列表请求,条件中的查询实际上不会被执行,firestore 只会查看规则并尝试确定请求是否根据提供的参数有效。如果它不能这样做,它将拒绝访问,即使从技术上讲,如果条件得到充分评估,所有资源都可以访问。
  • 你为什么说条件实际上不会被执行?你试过了吗?
  • 根据cloud.google.com/firestore/docs/security/rules-query 的文档,firestore 会根据其潜在结果集而不是所有文档的实际字段值来评估查询。在这种情况下,我正在检查不同集合中的特定值以确定用户是否应该具有访问权限,据我所知,没有办法从客户端模仿该查询,因此永远不会被允许。
  • 您能否提供更多关于您的数据当前结构的信息?您提到使用集合和子集合,但我不确定文档相对于用户、课程和资源如何适合其中。举一个文档的例子,在哪里可以找到资源,以及它在层次结构中的位置。另请注意,GCP Firestore 可能与 Firebase Firestore 不同,因此如果您的应用程序使用 Firebase,则应参考后者的文档。您可能需要查看此视频作为参考以获取帮助:youtube.com/watch?v=eW5MdE3ZcAw
  • 来自同一官方 Firebase 团队的另一个关于数据结构的视频:youtube.com/watch?v=haMOUb3KVSo
猜你喜欢
  • 2018-10-19
  • 2019-07-05
  • 1970-01-01
  • 1970-01-01
  • 2020-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多