多用户开放聊天应用的Firestore数据模型与安全规则设计咨询
关联现实活动的多用户聊天应用Firestore数据模型与安全规则探讨
应用核心需求
- 知晓Chat ID的用户可加入/退出群聊
- 加入群聊后可发送消息
- 用户可标记活动参与状态(attendance:参与/待定/拒绝)
- 用户仅能查看自己有参与状态的群聊
方案1:扁平化数据结构
数据模型
- /chat(collection) --- creator_id --- members [Array of userId] --- attendance [Array of user attendances Objects] - /messages (sub collection) --- sender_id
安全规则
match /chat/{chatId} { allow create : request.resource.data.creator_id == request.auth.uid; allow read : if request.auth != null allow list : if request.auth.uid in resource.data.members allow update : editingOnlyAllowedFields(["members", "attendance"]) && isCreatorOrMember(chatId); match /messages/{messageId} { // 读取权限与chat一致 allow create : request.resource.data.sender_id == request.auth.uid; allow update : resource.data.sender_id == request.auth.uid; } } function editingOnlyAllowedFields(allowedFields) { let editedKeys = request.resource.data.diff(resource.data).affectedKeys(); return editedKeys.hasOnly(allowedFields); } function isCreatorOrMember(chatId) { return resource.data.creator_id == request.auth.uid || request.auth.uid in resource.data.members; }
存在问题
前端可轻松筛选用户所属群聊,但任意成员都能移除他人或修改他人的参与状态,存在严重权限风险。
方案2:子集合拆分结构
数据模型
- /chat(collection) --- creator_id --- /attendance (sub collection) ----- userId (== 文档ID) ----- status --- /messages (sub collection) ----- sender_id
安全规则
function isChatMember(chatId) { return request.auth != null && exists(/databases/$(database)/documents/chats/$(chatId)/attendance/$(request.auth.uid)) } match /chat/{chatId} { allow get if request.auth != null allow list if isChatMember(chatId) // 此规则会触发子集合读取操作,另一种方案是用云函数在创建/attendance/userId时维护chat文档的成员数组 allow write if request.resource.data.creator_id == request.auth.uid match /attendance/{userId} { allow write if userId == request.auth.uid // 读取权限与chat一致 match /messages/{messageId} { // 读取权限与chat一致 allow create : request.resource.data.sender_id == request.auth.uid; allow update : resource.data.sender_id == request.auth.uid; } } }
存在问题
受Firestore「规则不是过滤器」的限制,前端无法直接通过子集合字段筛选群聊。需探讨可行解决方案,例如:
- 用Cloud Function维护群聊文档中的成员数组
- 批量查询用户参与的Chat ID
内容的提问来源于Stack Exchange,提问作者Nicolas Braun
相关产品推荐
相关产品推荐

