Firebase Firestore动态更新安全规则
假设我们有一个聊天应用程序,在这个应用程序中,我们有很多房间,一些是私人房间,一些是供每个人使用的。每个房间都有一个管理员,可以管理用户(可以邀请和删除)。只有房间里的人才能读写信息。管理员是在此场景中创建房间的人 我想在创建聊天室时创建安全规则,并在membersChange上更新它,这样只有会员才能读写留言板的内容 在这种情况下,它可能是这样的:Firebase Firestore动态更新安全规则,firebase,google-cloud-firestore,firebase-security,Firebase,Google Cloud Firestore,Firebase Security,假设我们有一个聊天应用程序,在这个应用程序中,我们有很多房间,一些是私人房间,一些是供每个人使用的。每个房间都有一个管理员,可以管理用户(可以邀请和删除)。只有房间里的人才能读写信息。管理员是在此场景中创建房间的人 我想在创建聊天室时创建安全规则,并在membersChange上更新它,这样只有会员才能读写留言板的内容 在这种情况下,它可能是这样的: databse/rooms/ private1 admin: memberX
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控制台中手动更新它们?或者是否有任何方法可以自动化此过程?
我注意到我可以。这里的流程应该是什么?我什么时候叫它?如何从数据库中获取成员
编辑:
对于任何想了解更多信息的人,我会重新考虑这个模型。我没有一直更新安全规则,而是看到了几种可行的方法: 选项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 您可以保存哪些用户可以访问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。或者您可以将这些技术中的多个结合起来。我的想法是展示一些可能性,以便您可以选择适合您的房间。每个房间都有不同的规则,并动态更新规则是个坏主意。以下是使用此解决方案时想到的几个问题:
- 谁将更新规则
- 同时创建两个房间时会发生什么情况
- 出问题时会发生什么
- 当你有一百万间房间时,你将如何维持你的规则
- 也
数据库/rooms/public/…
和数据库/rooms/private/…
为了保护您的私人房间,您可以查看并执行以下操作:如果成员的UID位于/members
(伪代码,不会这样工作)
你可以看一个例子。为每个房间制定不同的规则并动态更新规则是个坏主意。以下是使用此解决方案时想到的几个问题:
- 谁将更新规则
- 同时创建两个房间时会发生什么情况
- 出问题时会发生什么
- 当你有一百万间房间时,你将如何维持你的规则
- 也
数据库/rooms/public/…
和数据库/rooms/private/…
为了保护您的私人房间,您可以查看并执行以下操作:如果成员的UID位于/members
(伪代码,不会这样工作)
您可以查看一个示例。这听起来像是一个糟糕的做法,或者可能是XY问题。例如,是否有可能更改您的数据库结构?@AndréKool有可能,但如何在不丢失某些功能的情况下进行更改?为什么这是一种不好的做法呢?我建议你研究一下,如果会员的UID在/members中,会员可以读/写什么,以获得一个可能的解决方案