【发布时间】:2021-01-05 11:39:10
【问题描述】:
在我使用 Firestore 的 1-1 聊天应用程序中,2 位参与者将读取/写入 msgs 子集合中的文档,其中每个文档是一条消息。
但是由于安全规则,权限被拒绝而失败。
数据库结构:
chatRooms/
${roomId}/
msgs/
${msgId}
我想添加安全规则,以便只有相关的 2 个参与者能够在他们的 roomId 文档的 msgs 子集合中读/写
我编写了以下安全规则。
它让参与者在msgs 子集合中创建一个新文档(即发送消息)。
但用户无法阅读此msgs 子集。
match /chatRooms/{roomId} {
allow read: if request.auth.uid == resource.data.userA.id ||
request.auth.uid == resource.data.userB.id;
allow create: if request.auth.uid == request.resource.data.userA.id ||
request.auth.uid == request.resource.data.userB.id;
match /msgs/{msgId} {
allow read: if request.auth.uid == resource.data.sender._id ||
request.auth.uid == resource.data.partner._id;
allow create: if request.auth.uid == request.resource.data.sender._id ||
request.auth.uid == request.resource.data.partner._id;
}
}
读取的代码是:
const roomId = `${userAId}_${userBId}`;
const query = db.collection('chatRooms').doc(roomId).collection('msgs')
.orderBy('createdAt', 'desc')
.startAfter(lastVisible)
.limit(10)
query.get()
如果我像下面这样更改读取规则,则读取和写入工作完全正常。
所以我们可以确定问题出在msgs 子集合的读取规则中。 (而不是在其父集合/文档规则中)
match /msgs/{msgId} {
allow read: if request.auth != null;
allow create: if request.auth.uid == request.resource.data.sender._id ||
request.auth.uid == request.resource.data.partner._id;
}
更新:
Frank 提出了 3 个解决方案,我尝试了其中的两个(1 和 3),但都对我不起作用。
对于解决方案 1,我添加了一个带有参与者 UID 的 ids 数组。
写入消息(添加新文档)使用相同的安全规则。
读取操作如下所示:
这是安全规则:
更新 2
正如弗兰克在他的回答中的评论中提到的那样,它在修复安全规则后起作用。 (因为这个评论在下面,我也在这里添加它)
match /msgs/{msgId} {
allow read: if request.auth.uid in resource.data.ids;
allow create: if request.auth.uid in request.resource.data.ids;
}
更新 3
解决方案 1 需要生成一个索引(我也使用orderBy),这需要额外付费。所以我也尝试了弗兰克的解决方案 3,但它返回权限被拒绝错误。
可能读取查询是错误的,它需要一些过滤器,但我不能按照规则的要求在$roomId doc 数据(userA.id / userB.id)上添加过滤器,同时从msgs 集合中读取。
规则:
match /chatRooms/{roomId=**} {
allow read: if request.auth.uid == resource.data.userA.id ||
request.auth.uid == resource.data.userB.id;
allow create: if request.auth.uid == request.resource.data.userA.id ||
request.auth.uid == request.resource.data.userB.id;
allow update: if request.auth.uid == resource.data.userA.id ||
request.auth.uid == resource.data.userB.id;
}
读取查询:
const query = dbFirestore.collection('chatRooms').doc(roomId).collection('msgs')
.orderBy('createdAt', 'desc')
.limit(10)
query.onSnapshot( ... )
【问题讨论】:
-
请不要发布您的代码截图或其他文本内容。而是发布实际文本,并使用 Stack Overflow 的格式化工具进行标记。
标签: javascript google-cloud-firestore firebase-security