Firestore(Swift)安全查询问题:如何合规查询用户集合?
这个问题的核心在于Firestore安全规则对单个文档读取(get)和集合查询(list)的验证逻辑不同,你的现有规则只覆盖了单个文档的权限,但没有针对查询操作做正确的约束。
为什么原来的查询会报错?
你当前的安全规则中,allow read: if request.auth.uid == userId; 里的userId是文档ID。当你通过文档ID直接get文档时,Firestore可以直接验证文档ID是否等于当前用户的uid,所以能成功。
但当你用whereField查询文档内的userId字段时,这属于集合级的list操作。Firestore需要确保查询返回的所有文档都符合安全规则,但它无法自动关联你查询的userId字段值和文档ID,所以会判定你的查询无法保证结果集里的每个文档都满足request.auth.uid == 文档ID,因此返回权限不足的错误。
解决方案:修改安全规则,适配查询操作
你需要拆分read权限为get(单个文档读取)和list(集合查询),并为list操作添加查询条件验证,确保查询的userId字段等于当前用户的uid:
service cloud.firestore { match /databases/{database}/documents { match /users/{userId} { // 单个文档读取:验证文档ID等于用户uid allow get: if request.auth.uid == userId; // 集合查询:验证查询条件包含userId字段等于当前用户uid allow list: if request.auth != null && request.query.where("userId", "==", request.auth.uid); // 保持原有更新、删除、创建的规则 allow update, delete: if request.auth.uid == userId; allow create: if request.auth.uid != null; } } }
为什么这样能生效?
Firestore的request.query对象可以访问你查询时设置的条件,当你执行whereField("userId", isEqualTo: userId)时,规则会检查这个查询条件是否严格匹配request.auth.uid,这样Firestore就能确认返回的所有文档都符合权限要求,允许查询执行。
额外提示
如果你能保证文档内的userId字段和文档ID始终一致,也可以尝试简化规则,但不推荐——因为resource.data.userId在集合查询时会要求Firestore扫描所有文档验证条件,会影响性能。而用request.query的方式是前置验证,不会产生额外性能开销。
内容的提问来源于stack exchange,提问作者David Cittadini

