【问题标题】:Firebase Security rules to restrict access on all paths but one?Firebase 安全规则来限制除一条以外的所有路径的访问?
【发布时间】:2019-04-15 19:53:03
【问题描述】:

问题:

对于下面不同的顶级 firestore 集合,如何限制对除一个路径之外的所有路径的访问?

我们正在 Firestore 中构建数据架构,以支持跨多所学校的教师聊天应用。

顶级 Firestore 集合包括:

  • /siteAdminUsers
  • /schools
  • /schools/{schoolId}/teachers
  • /schools/{schoolId}/chats

以下是我们现在正在尝试的安全规则设置 - 我们检查的地方:

  1. 有效的用户授权
  2. 预期值存在于 userClaim 变量 request.auth.token.chatFlatList

但是,/messages 的读取侦听器被阻止。

错误信息:

FirebaseError:[code=permission-denied]:权限缺失或不足


service cloud.firestore {
  match /databases/{database}/documents {

    match /{document=**} {
      allow read, write: if false;
    }

    match /schools/{schoolId}/chats/{discussionId}/messages {
      allow write: if false;
      allow read: if request.auth != null
                  && request.auth.token != null
                  && request.auth.token.chatFlatList.val().contains($discussionId);
    }
}

详情

我们正在使用云功能来读​​取/写入所有数据,因此对于几乎所有情况,我们都可以阻止所有客户端访问。

一个例外是聊天讨论,我们需要在移动客户端中设置一个快照监听器以了解何时有新消息。

子集备注:

在学校,有针对学校工作人员(教师、管理员等)的讨论会

/schools/{schoolId}/chats/{discussionId}

每个讨论文档包含:

  1. 参与者教师 ID 列表
  2. 实际消息的子集合,其中每个文档都是单独发布的消息:

/schools/{schoolId}/chats/{discussionId}/messages

来自 Cloud Function 的用户声明代码

查看云函数日志,我们已经验证了 userClaim 正在被设置。

return firebaseAdmin
    .auth()
    .setCustomUserClaims(
        uid, {
            chatFlatList: 'id1 id2 id3'
        }
    );

更新 #1

尝试了以下变体,其中规则跳过/省略对 userClaim 和 auth.token 的检查。

但是,还是一样的权限错误。

service cloud.firestore {
  match /databases/{database}/documents {

        match /{document=**} {
          allow read, write: if false;
        }

        match /schools/{schoolId}/chats/{discussionId}/messages {
          allow write: if false;
          allow read: if request.auth != null;
        }

    }
}

【问题讨论】:

  • 您是否尝试过简单地允许所有消息访问,只是为了查看问题是否与 chatFlatList 的解释有关?
  • @Doug,帖子已更新为您所描述的尝试规则设置的列表。我想知道 - 是不是主要的 "global rule" match /{document=**} 以某种方式覆盖了消息的自定义规则?我试图在文档中找到一些内容来解释是否至少有 1 条规则与 true 匹配,那么这就足够了.. 不确定我是否错过了那个细节,但没有看到它。谢谢
  • 您可以像这样拒绝整个数据库,然后允许特定部分。这是完全可行的。您只是不能允许数据库的某些部分,然后再拒绝它。一旦被允许,就始终允许该用户使用。
  • 由于 firebase 控制台要求提供反馈 - 在这一点上,我想借此机会说:总体而言,不同的 Firebase 层级都可以直接升级和使用。但是 - 恭敬地(这里是 Firebase 的大拥护者!) - 安全规则区域一直是导航/管理最麻烦的(不是那么直观)。例如。似乎没有真正的方法来调试规则逻辑中的错误。模拟器不支持调试日志来确定哪个规则匹配真假,也不允许 userClaim cfgs。规则 cfg 有效或无效:(。任何指导,非常受欢迎 :)。谢谢
  • 我了解,这些是 Firebase 人员正在考虑的问题。

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


【解决方案1】:

我认为这里的问题是您正在为名为消息的集合编写规则。

所有匹配语句都应该指向文档,而不是集合。 https://firebase.google.com/docs/firestore/security/rules-structure

您应该尝试在消息路径后添加 /{document=**},例如:

    match /schools/{schoolId}/chats/{discussionId}/messages/{document=**} {
      allow write: if false;
      allow read: if request.auth != null;
    }

【讨论】:

    【解决方案2】:

    这是一个解决方案(似乎有效),其中包括检查chatFlatList 用户声明变量(来自原始问题)的子字符串:

            match /schools/{schoolId}/chats/{discussionId}/messages {
              allow write: if false;
              allow read: if request.auth != null
              && request.auth.token.chatFlatList.matches(discussionId);
            }
    

    感谢:

    1. Firebase storage rules based on custom parameters

      • 这里的帖子显示没有任何$ 符号来访问路径变量。我记得在 安全规则 示例代码示例中看到了这一点 - 也许它特定于数据库层?
    2. https://firebase.google.com/docs/reference/security/storage/#string

    3. https://regex-golang.appspot.com/assets/html/index.html

      • 在这里尝试一些示例输入,以了解如何创建正则表达式。

    【讨论】:

      【解决方案3】:

      如果我想读取和写入所有集合而不是一个名为“backStage”的集合,这对我有用;

      rules_version = '2';
          service cloud.firestore {
            match /databases/{database}/documents {
              match /{collection}/{document} {
                allow read: if true
                allow write: if (collection != "backStage");
              }
            }
          }
      

      【讨论】:

        猜你喜欢
        • 2013-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-31
        相关资源
        最近更新 更多