Firebase Realtime Database基于data.child的读取规则不生效问题
规则配置的核心错误
- 属性路径匹配错误:你在
/items节点层级配置的.read判断逻辑data.child('isDelete').val() == false,检查的是**/items节点自身的isDelete属性**。但从你给出的数据结构看,isDelete字段是存放在/items下的每个子条目(比如/items/1xxxxxxxxxx)上的,/items作为父节点本身没有这个属性,取值永远为null,判断条件恒不成立,这也是你在规则 playground 测试读/items路径直接被拒的直接原因。 - 违反Firebase Realtime Database安全规则的核心设计:安全规则不是数据过滤器。很多人误以为规则可以在读取父节点时自动遍历子节点、筛掉不符合条件的条目返回部分结果,实际上规则是访问授权校验逻辑,只要你发起读取整个
/items节点的请求,规则不会逐层检查子节点权限,只要父节点授权不通过就直接拒绝;就算你把读权限开到子节点,读取父节点的请求只要发现任意一个子节点无读权限,整个请求也会直接报错,永远不会返回部分匹配的结果。 - 写规则覆盖不全:当前配置的写规则仅允许创建不存在的新条目,后续编辑条目、更新isDelete状态做软删除的操作完全没有权限,不符合常规软删除业务的使用需求。
修正方法
Firebase 安全规则本身不支持自动过滤数据,要实现仅获取isDelete=false条目的需求,必须同时调整查询逻辑和安全规则:
- 调整客户端查询逻辑,不要直接拉取整个
/items节点,查询时主动带上isDelete=false的过滤条件,以Web SDK为例:
import { getDatabase, ref, query, orderByChild, equalTo, get } from "firebase/database"; const db = getDatabase(); // 主动查询isDelete为false的条目 const validItemsQuery = query( ref(db, 'items'), orderByChild('isDelete'), equalTo(false) ); const res = await get(validItemsQuery);
- 修改安全规则,在
/items层级校验列表查询必须携带isDelete=false的过滤条件,同时补全单条读权限和合理的写权限:
{ "rules": { "items": { // 列表读权限:仅允许按isDelete排序、且查询isDelete=false的请求 ".read": "query.orderByChild == 'isDelete' && query.equalTo == false", // 给isDelete字段加索引,优化查询性能 ".indexOn": "isDelete", "$itemId": { // 单条读权限:未被删除的条目允许读取,适配单条内容查询场景 ".read": "data.child('isDelete').val() == false", // 写权限:登录用户可创建新条目,条目创建者可编辑/软删除自己的内容,可根据自身业务调整权限范围 ".write": "auth != null && (!data.exists() || data.child('creatorId').val() == auth.uid)", // 字段校验:isDelete必须是布尔值 "isDelete": { ".validate": "newData.isBoolean()" } } } } }
注意:上面写规则里用到的creatorId字段,需要你在创建条目时把当前登录用户的uid存在条目数据里,如果你不需要做创建者权限控制,也可以根据自身业务调整写规则的判断逻辑。
内容的提问来源于stack exchange,提问作者cieux123
相关产品推荐
相关产品推荐

