Firestore动态更新安全规则

时间:2018-08-08 12:41:36

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

想象一下,我们有聊天应用程序,并且在此应用程序中,我们有很多房间,有些房间是私人的,有些则适合所有人。每个房间都有一个可以管理用户(可以邀请和删除)的管理员。只有会议室成员可以读取和写入消息。管理员是在这种情况下创建房间的人。

我想在创建房间时创建安全规则,并在membersChange上对其进行更新,以便只有成员才能读写留言板的内容。

在这种情况下,它就是这样:

databse/rooms/
             private1 
                admin: memberX
                members: member1, member2
                //only admin can write into members fields
                messages
                    message1...
                    message2...
                    message3...
                //only members can write and read messages

             private2 
                admin: memberXY
                members: member1, member4
                //only admin can write into members fields
                messages
                    message1...
                    message2...
                    message3...
                //only members can write and read messages

是否可以通过云功能创建和更新安全规则,而不是在Firebase控制台中手动更新安全规则?还是有任何方法可以自动执行此过程?

我注意到我可以deploy security rules using CLI。这里的程序应该是什么?我什么时候叫它?如何从数据库中获取成员?

编辑: 对于任何需要更多信息的人,请查看How to Build a Secure App in Firebase

2 个答案:

答案 0 :(得分:2)

我会重新考虑这个模型。我看到了几种可行的方法,而不是一直更新安全规则:

选项1

您可以保存哪些用户可以访问Firestore上的特定房间,然后根据安全规则访问该房间的文档,并查看授权用户列表中是否有经过身份验证的用户。这样做的问题是成本,因为这将触发每个操作额外的数据库读取,这可能会变得昂贵。

选项2

您可以使用云功能为用户创建自定义声明,如下所示:

admin.auth().setCustomUserClaims(uid, {"rooms": "room1,room2"})

然后根据安全规则,您可以检查用户是否对特定房间拥有所有权:

match /rooms/{roomId} {
  allow read: if roomId in request.auth.token.rooms.split(',');
}

我相信您也可以将声明直接保存为数组,但我尚未对其进行测试。

对于此选项,您需要考虑令牌的大小,令牌的大小是有限制的,如果令牌太大,则会导致性能问题。根据您的方案,您可以创建较小的权限集,然后将其设置为房间和用户。

选项3

您可以保存可以访问每个文档的用户的uid,然后检查该文档上是否存在经过身份验证的用户的uid。但是,如果您有太多的用户,这可能会失控。

如果您的情况有意义,我会选择选项2。或者,您可以结合使用其中一种以上的技术。我的想法是展示一些可能性,以便您可以选择最适合自己的方式。

答案 1 :(得分:2)

为每个房间设置不同的规则并动态更新规则是一个坏主意。以下是此解决方案引起的几个问题:

相反,您首先可以将数据结构分为公共房间和私人房间:database/rooms/public/...database/rooms/private/...

要保护您的私人房间,您可以看一下rules conditions并执行类似的操作:member can read/write IF his UID is in /members(伪代码,将无法正常工作)。

您可以查看this question作为示例。