Firebase安全性规则可以限制除一条路径以外的所有路径的访问权限?

时间:2018-11-13 03:13:27

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

  

问题:

     

对于以下不同的顶级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;
        }

    }
}

3 个答案:

答案 0 :(得分:3)

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

  

所有match语句应指向文档,而不是集合。   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;
    }

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

这是一个解决方案(似乎正在工作),其中包括检查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

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

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

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