Firestore安全规则PERMISSION_DENIED问题:模拟器正常真机报错
解决Firestore集合查询权限拒绝问题
问题根源
你的安全规则仅授权用户访问自己的单个文档(/Users/{UserId}),但Flutter应用执行的是集合级查询(Query(Users order by name))。Firestore安全规则默认会拒绝未明确授权的集合操作,且集合查询需要规则能验证查询结果中的每一个文档都符合权限要求,当前规则无法做到这一点,因此触发PERMISSION_DENIED。
解决方案
根据你的业务需求,有两种修复方式:
方式1:直接查询单个用户文档(推荐)
如果个人资料页只需要当前用户的信息,不要对整个Users集合做查询,而是直接通过用户UID获取对应文档。Flutter代码修改为:
// 获取当前用户UID final currentUserUid = FirebaseAuth.instance.currentUser?.uid; if (currentUserUid != null) { // 直接查询单个文档,匹配你的原有规则 final docSnapshot = await FirebaseFirestore.instance .collection('Users') .doc(currentUserUid) .get(); }
这种方式下,你最初的安全规则完全适用,无需修改。
方式2:修改规则支持集合查询
如果业务确实需要集合查询(比如需要筛选特定用户),需调整规则确保查询仅返回当前用户有权限访问的文档,同时验证查询本身包含正确的过滤条件:
service cloud.firestore { match /databases/{database}/documents { // 单个文档的读写权限 match /Users/{userId} { allow read, write: if request.auth != null && request.auth.uid == userId; } // 集合查询权限:仅允许查询包含当前用户UID过滤条件的请求 match /Users { allow list: if request.auth != null && request.query.where('uid', '==', request.auth.uid); } } }
同时,Flutter代码中的查询必须加上对应的过滤条件,否则仍会被拒绝:
final currentUserUid = FirebaseAuth.instance.currentUser?.uid; if (currentUserUid != null) { final querySnapshot = await FirebaseFirestore.instance .collection('Users') .where('uid', isEqualTo: currentUserUid) .orderBy('name') .get(); }
注意事项
- 模拟器测试集合查询时,必须模拟包含
uid == 当前用户UID的过滤条件,否则测试结果会和真机不一致。 - 确保
Users集合中的每个文档都包含uid字段,且字段值与文档ID(用户UID)一致,否则规则会失效。
内容的提问来源于stack exchange,提问作者Mthomas
相关产品推荐
相关产品推荐

