如何为使用childByAutoId存储的Firebase用户设置安全实时数据库规则
Firebase实时数据库规则配置:用户仅能读写自身数据
问题核心
你的场景是Users节点下用childByAutoId()生成随机ID子节点,每个子节点包含与节点ID一致的id字段,但现有规则无法实现“用户仅能读写自身数据”的需求——原因在于默认的节点ID匹配auth.uid逻辑不适用(随机生成的节点ID和Firebase Auth的uid完全无关),必须通过节点内存储的用户身份标识字段来做校验。
正确规则配置
{ "rules": { "Users": { "$userNodeId": { // 读取权限:已认证用户且节点内的uid字段等于当前用户auth.uid ".read": "auth != null && data.child('uid').val() == auth.uid", // 写入权限:已认证用户;创建时新数据必须包含当前用户的auth.uid;更新时仅能修改自身节点 ".write": "auth != null && (data.exists() ? data.child('uid').val() == auth.uid : newData.child('uid').val() == auth.uid)" } } } }
关键调整说明
节点数据必须包含
auth.uid字段
你需要在创建用户节点时,将当前登录用户的Firebase Authuid写入节点(而非仅存储节点ID作为id)。iOS端创建用户数据的代码示例:guard let currentUser = Auth.auth().currentUser else { return } let userRef = Database.database().reference().child("Users").childByAutoId() let userData = [ "id": userRef.key!, // 保留原有的节点ID字段 "uid": currentUser.uid, // 新增存储用户Auth uid的字段 "name": "示例用户名", "email": currentUser.email ?? "" ] userRef.setValue(userData)规则逻辑解析
$userNodeId匹配Users下的任意随机子节点ID.read:仅允许已认证用户读取自身节点(通过节点内的uid与auth.uid匹配).write:- 创建节点时:强制新数据的
uid等于当前用户auth.uid,防止恶意创建他人节点 - 更新节点时:仅允许修改自身节点(已存在节点的
uid与auth.uid匹配)
- 创建节点时:强制新数据的
iOS端正确读取自身数据
登录后,通过uid字段查询自身节点,而非遍历所有用户:
guard let currentUser = Auth.auth().currentUser else { return } let usersRef = Database.database().reference().child("Users") usersRef.queryOrdered(byChild: "uid") .queryEqual(toValue: currentUser.uid) .observeSingleEvent(of: .value) { snapshot in guard let userEntries = snapshot.value as? [String: [String: Any]] else { return } for (nodeId, userData) in userEntries { print("自身节点ID:\(nodeId),数据:\(userData)") // 处理用户数据 } }
为什么原有规则失效?
如果你的原有规则是通过$userNodeId == auth.uid做校验,由于childByAutoId()生成的是随机字符串,和Firebase Auth分配的uid完全不匹配,规则会直接拒绝访问。必须通过节点内存储的auth.uid字段来建立用户与节点的关联。
内容的提问来源于stack exchange,提问作者Nitin Gohel
相关产品推荐
相关产品推荐

