Firestore查询成员聊天列表权限被拒,安全规则如何修正?
Firestore查询成员聊天时出现权限拒绝错误
需求
查询所有当前用户作为成员的聊天并监听其更新。
Firestore结构
/chats/{chatId}
前端查询代码
// cut const chatsQuery = query( collection(firestore, "chats"), where('members', 'array-contains', userId), orderBy('lastActivity', 'desc'), ).withConverter(converter) const unsubscribe = onSnapshot(chatsQuery , (snapshot) => snapshot.docChanges().forEach((change) => { /* ... */ })) // cut
当前Firestore安全规则
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { function isAuthenticated() { return request.auth != null; } match /chats/{chatId} { allow read: if isAuthenticated() && request.auth.uid in resource.data.members; } } }
控制台错误信息
client.js?4d30:1 [2023-04-02T14:55:07.984Z] @firebase/firestore: Firestore (9.18.0): Uncaught Error in snapshot listener: FirebaseError: [code=permission-denied]:
evaluation error at L9:22 for 'list' @ L9
问题原因
权限错误的核心原因是:集合查询(list操作)时,安全规则里的resource.data无法被访问。resource对象仅在单个文档的读取(get操作)时存在,而你执行的是集合级别的查询,Firestore在处理list请求时不会逐个加载文档检查resource.data.members,直接引用resource.data会导致规则评估失败。
解决方案
修改安全规则,分别处理单个文档读取(get)和集合查询(list):
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { function isAuthenticated() { return request.auth != null; } match /chats/{chatId} { // 单个文档读取:验证用户在该聊天的成员列表中 allow get: if isAuthenticated() && request.auth.uid in resource.data.members; // 集合查询:验证查询条件为members包含当前用户UID,确保查询结果仅返回用户有权限的文档 allow list: if isAuthenticated() && request.query.where != null && request.query.where.members['array-contains'] == request.auth.uid; } } }
这样修改后:
- 单个聊天文档读取时,规则直接验证用户是否在该文档的成员数组中
- 集合查询时,规则校验你的查询条件确实是
members array-contains 当前用户UID,Firestore会自动过滤符合条件的文档,同时确保规则通过
内容的提问来源于stack exchange,提问作者Roman Mahotskyi
相关产品推荐
相关产品推荐

