Flutter中Firestore安全规则权限拒绝问题求助
问题背景
使用Firebase Firestore存储数据,设置的安全规则要求:仅当用户认证UID存在于目标文档的userSessions数组中时,才允许访问该文档。安全规则代码如下:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /mock_text/{document}/{path=**} { allow read, write: if request.auth.uid in get("/databases/$(database)/documents/mock_text/$(document)/").data.userSessions; } } }
通过后端维护userSessions列表,功能正常。在Flutter应用中使用匿名认证,执行以下查询时触发权限拒绝错误:
final query = _firestore .collection("mock_text") .where("userSessions", arrayContains: currentUser!.uid);
错误信息:
FirebaseException ([cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation.)
已确认Firestore与Auth连接正常(将规则改为request.auth.uid != null可正常运行),且规则在Firestore测试平台中验证有效。
问题根源
当前安全规则使用get()调用获取目标文档数据来验证权限,这种方式仅适用于单个文档的读写操作(比如doc("xxx").get())。但在执行集合查询时,Firestore需要提前判断整个查询是否符合规则,无法为每个待匹配的文档单独执行get()操作(存在性能和安全限制),因此会直接返回权限拒绝。
解决方案
1. 修改安全规则
将规则中的get()调用替换为直接访问当前文档的resource对象,resource代表当前正在被访问的文档,在集合查询场景下可以直接读取其数据:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /mock_text/{document}/{path=**} { allow read, write: if request.auth != null && request.auth.uid in resource.data.userSessions; } } }
添加request.auth != null的前置检查,避免未认证用户触发不必要的验证逻辑。
2. 保留现有Flutter查询逻辑
你的Flutter查询代码是正确的,where("userSessions", arrayContains: currentUser!.uid)会筛选出包含当前用户UID的文档,和修改后的规则逻辑完全匹配,无需调整。
验证
修改规则后,重新执行Flutter查询即可正常获取数据。若仍有问题,可检查:
- 当前用户的UID确实存在于目标文档的
userSessions数组中 - 匿名认证已成功完成,
currentUser不为空
内容的提问来源于stack exchange,提问作者Guilherme Maia

