Firebase实时数据库安全规则中如何打印auth及排查uid匹配问题
Firebase实时数据库安全规则auth.uid不符问题排查
问题描述
初始疑问
调用Firebase实时数据库时,能不能在Security Rules里打印或返回auth的负载?现在规则不生效,怀疑auth.uid不是预期值,想确认它的实际数值。
问题更新
规则里这两行判断结果不对劲:
root.child('projects').child($project_uuid).child('person').child('22').exists() // 结果为true root.child('projects').child($project_uuid).child('person').child(auth.uid).exists() // 结果为false
我预期auth.uid是22,按道理第二行也该是true,但实际不是。看了Network>ws下的发送数据,还是觉得auth.uid应该是22,想知道这是怎么回事。
最小复现示例
数据库内容
projects: { "abcd": { person: { 22: { permissions: { read: true } } }, data: { allKindOfData: "abc" } } }
安全规则
{ "rules": { "projects": { "$project_uuid": { "person": { ".read": "true" }, ".read": "root.child('projects').child($project_uuid).child('person').child('22').exists() && root.child('projects').child($project_uuid).child('person').child(auth.uid).exists()" } } } }
问题排查与解决
1. 没法直接打印auth负载,但能间接验证
Firebase安全规则不支持直接打日志,但可以通过构造规则判断来确认auth的实际值:
- 临时加个测试规则,比如在某个节点的
.read里写auth.uid === '22',看能不能访问——能访问就说明auth.uid确实是22,反之则不是 - 也可以用
auth.token里的其他字段(比如email)辅助验证用户身份是否正确
2. 可能的问题原因
(1) 数据类型不匹配
数据库里person节点下的键是数字类型的22,但auth.uid是字符串类型,这时候child(auth.uid)会去找字符串键"22",但数据库里实际是数字键22,自然匹配不上。
解决办法:统一数据类型——要么把数据库里的键改成字符串"22",要么在规则里转类型:
// 把auth.uid转成字符串适配数据库键类型 root.child('projects').child($project_uuid).child('person').child(auth.uid + '').exists() // 或者把auth.uid转成数字适配数据库键类型 root.child('projects').child($project_uuid).child('person').child(Number(auth.uid)).exists()
(2) 用户身份没正确验证
虽然你在Network里看到了数据,但当前请求可能根本没带有效的认证信息:
- 检查客户端有没有完成Firebase Auth的登录流程
- 确认请求时的用户会话是否有效,有没有登录过期或者切换用户的情况
(3) 规则优先级问题
当前规则里$project_uuid下同时定义了person节点的.read: true和父节点的.read规则。Firebase安全规则是优先匹配最具体的规则:访问projects/abcd/person时会用person节点的规则(允许读取),但访问projects/abcd或者projects/abcd/data时,会触发父节点的.read规则,这时候就需要auth.uid匹配。如果你的测试是访问后者,那就要确认auth.uid的问题。
3. 验证步骤建议
- 临时改规则,把
.read设为auth.uid === '22',通过是否能访问来判断auth.uid是否正确 - 去Firebase控制台看
person节点下的键是数字还是字符串 - 在客户端代码里直接打印
auth.currentUser.uid,确认它的值是不是22
内容的提问来源于stack exchange,提问作者Marty
相关产品推荐
相关产品推荐

