Firestore安全规则:列表查询(array-contains)如何获取resource.data底层值?
Firestore安全规则中无法直接获取array-contains查询的具体值
在Firestore列表查询的安全规则里,你没法直接获取array-contains查询中指定的那个具体值,这也是你之前的规则返回false的核心原因。
为什么原来的代码行不通?
当你在列表规则中访问resource.data.sharedWithIds时,它并不是文档实际存储的数组数据,而是查询施加的约束条件(也就是你debug输出里的constraint_value结构)。这个约束只表示“该字段包含某个值”,但不会暴露具体的那个值,所以你调用split("_")根本无法生效——它不是字符串类型,而是一个约束对象。
解决方案
针对你的场景,有两种可行的调整思路:
1. 调整数据结构(推荐)
提前在文档中存储拆分后的独立UID列表,避免在规则中处理字符串拆分。比如给文档新增一个sharedWithUids字段,专门存储所有独立的用户UID:
// 文档数据示例 someResource{ sharedWithIds: ["client1", "client2", "admin1", "admin2", "admin1_client1"], sharedWithUids: ["client1", "client2", "admin1", "admin2"] // 提前拆分好的独立UID }
对应的查询改为直接针对独立UID的array-contains:
getDocs(query(collection, where("sharedWithUids", "array-contains", request.auth.uid)))
安全规则简化为:
match /resources/{resourceId}{ allow list: if request.auth.uid in resource.data.sharedWithUids; }
这种方式既符合Firestore规则的评估逻辑,也能保证查询和权限验证的效率。
2. 调整权限验证逻辑(不推荐,仅当无法修改数据时使用)
如果没法修改现有数据结构,你可以换一种权限判断逻辑:直接验证当前用户的UID是否存在于sharedWithIds数组中,或者是否存在以当前UID开头的组合ID。但Firestore规则没有字符串包含的原生方法,你需要提前枚举所有可能的组合并通过hasAny验证,这种方式扩展性差,仅适用于固定组合场景:
match /resources/{resourceId}{ allow list: let userUid = request.auth.uid; let allowedCombinations = [userUid, `${userUid}_client1`, `${userUid}_client2`]; // 枚举所有可能的组合 return resource.data.sharedWithIds.hasAny(allowedCombinations); }
总结
直接获取array-contains查询的具体值在Firestore安全规则里是行不通的,最稳妥的方式是调整数据结构,提前存储需要用于权限验证的独立字段。
内容的提问来源于stack exchange,提问作者vir us
相关产品推荐
相关产品推荐

