Firestore安全规则中resource.data始终为空对象是否为Bug?
这不是Bug,是递归路径匹配导致的集合/文档权限区分问题
你遇到的现象并不是Firestore安全规则的Bug,而是因为你使用了递归路径匹配({document=**}),这个匹配规则会同时作用于hospitals集合本身以及它下面的所有文档、子集合。
问题原因拆解
当你执行集合级别的查询(比如db.collection("hospitals").get())时:
- 规则会先检查
hospitals集合本身的权限,此时resource代表的是集合而非单个文档,集合没有实际数据内容,所以resource.data是空对象。- 这就是
allow read :if resource.data.size() == 0返回true的原因——集合的resource.data确实是空的。 - 而
resource.data.name != null会返回false,因为空对象里根本没有name字段,导致集合的读取权限被拒绝,整个查询直接失败,哪怕你要读取的文档本身包含name字段。
- 这就是
- 只有当你查询单个文档(比如
db.collection("hospitals").doc("xxx").get())时,resource才会指向该文档的实际数据,此时resource.data.name != null才会根据文档内容判断是否生效。
解决办法
根据你的需求选择以下两种方案:
方案1:仅匹配hospitals下的直接文档(不含子集合)
如果你的hospitals集合下没有需要权限控制的子集合,把匹配规则改成只针对单个文档:
service cloud.firestore { match /databases/{database}/documents { match /hospitals/{hospitalId} { allow read :if resource.data.name != null; } } }
这样规则只会作用于hospitals下的单个文档,集合级查询时会自动检查每个文档的name字段是否存在。
方案2:保留递归匹配,区分集合和文档的权限
如果需要包含子集合的权限控制,你需要在规则中区分集合和文档的情况:
service cloud.firestore { match /databases/{database}/documents { match /hospitals/{document=**} { // 允许读取集合(resource.data为空),同时允许读取存在name字段的文档/子集合文档 allow read: if resource.data.size() == 0 || resource.data.name != null; } } }
这个规则会允许集合级查询通过,同时确保所有被读取的文档都包含name字段。
内容的提问来源于stack exchange,提问作者Jack Ng
相关产品推荐
相关产品推荐

