调整Firebase实时数据库规则:普通用户无法创建数据的问题排查
问题
现有Firebase实时数据库规则在单用户场景下运行正常:
{ "rules": { ".read": "auth != null", ".write": "auth != null", "confirmations": { ".read": false, ".write": true } } }
尝试添加权限更低的用户后,新增用户无法在数据库中创建新对象,修改后的规则如下:
{ "rules": { ".read": "auth != null", // 所有已认证用户可读取 ".write": "auth.uid === 'AdminUID' || (!data.exists() && newData.exists())", ".validate": "auth.uid === 'AdminUID' || (!data.exists() && newData.exists())" } }
(已将AdminUID替换为实际UID,但问题仍存在:新增用户可读取但无法创建新数据,也无法修改现有数据)
期望权限:
- 管理员:拥有读取、修改、删除、创建数据的全部权限
- 普通用户:仅能读取和创建新条目,无法修改或删除现有数据
解决方案
问题出在规则的作用层级和逻辑判断上:
- 根节点的
data.exists()判断不适用子节点创建:当普通用户尝试在根节点下创建子节点时,根节点本身是存在的,所以根节点规则中的!data.exists()会返回false,导致普通用户的写入条件不成立。 - 冗余的
.validate规则:.validate用于验证数据格式,这里不需要重复写入权限的判断,反而可能干扰正常的写入逻辑。
正确的规则应该针对子节点层级设置权限,示例如下:
{ "rules": { ".read": "auth != null", // 所有已认证用户可读 ".write": "auth.uid === 'AdminUID'", // 管理员拥有根节点级别的全权限(包括删除根下所有数据) "$nodeId": { // 匹配所有子节点 ".write": "auth.uid === 'AdminUID' || (!data.exists() && newData.exists())" // 管理员可修改/删除该子节点;普通用户仅能创建新子节点(该节点不存在时写入) }, "confirmations": { // 保留原有的confirmations节点规则(如果需要) ".read": false, ".write": "auth != null" // 或根据需求调整权限范围 } } }
规则说明
- 根节点的
.write仅开放给管理员,防止普通用户误删整个根节点下的数据。 - 通过
$nodeId匹配所有子节点,针对单个子节点判断权限:- 管理员UID匹配时,拥有该子节点的全部写入权限(创建、修改、删除)。
!data.exists() && newData.exists()确保普通用户只能创建新的子节点,无法修改或删除已存在的节点。
- 如果不需要保留
confirmations节点的特殊规则,可以直接删除该部分。
内容的提问来源于stack exchange,提问作者Dominick
相关产品推荐
相关产品推荐

