Firebase Realtime Database模拟读取权限被拒求助:Android端私密笔记应用Google登录权限配置问题
我仔细梳理了你的问题描述、数据库结构和规则配置,找到了几个核心问题导致模拟读取失败,下面逐一分析并给出针对性解决方案:
1. 数据库结构与规则逻辑不匹配
你当前的规则定义了items/$uid的权限校验,期望用户的笔记数据存储在以自己UID命名的子节点下,但实际你的数据库结构中,items节点直接包含的是笔记条目(比如-MwtOrIBmhaoiGtSjzRl),完全没有按用户UID划分目录。这种情况下,规则里的$uid变量永远无法匹配到实际路径,自然会触发读取拒绝。
解决方案A:调整数据库结构(推荐,符合Firebase最佳实践)
重新组织数据,让每个用户的笔记都归属于自己UID对应的子节点下,结构示例如下:
{ "items": { "e41ac05f-6c93-40c8-add6-90bccf8ab80d": { "-MwtOrIBmhaoiGtSjzRl": { "key": "-MwtOrIBmhaoiGtSjzRl", "modifiedAt": "2022-02-27 04:19:15.782677", "string": "test11" }, "-MwvRBvCJ3hVJS3Qx1M3": { "key": "-MwvRBvCJ3hVJS3Qx1M3", "modifiedAt": "2022-02-27 13:48:43.081140", "string": "Test2" } } } }
对应的规则可以保留你原本的配置:
{ "rules": { "items": { "$uid": { ".read": "$uid === auth.uid", ".write": "$uid === auth.uid" }, ".indexOn": "modifiedAt" } } }
解决方案B:修改规则适配现有结构
如果暂时不想调整数据结构,需要给每个笔记节点添加uid字段(存储创建该笔记的用户UID),然后通过规则校验当前用户UID与笔记的uid字段是否一致:
首先更新你的笔记数据,每个条目补充uid字段:
{ "items": { "-MwtOrIBmhaoiGtSjzRl": { "key": "-MwtOrIBmhaoiGtSjzRl", "modifiedAt": "2022-02-27 04:19:15.782677", "string": "test11", "uid": "e41ac05f-6c93-40c8-add6-90bccf8ab80d" }, "-MwvRBvCJ3hVJS3Qx1M3": { "key": "-MwvRBvCJ3hVJS3Qx1M3", "modifiedAt": "2022-02-27 13:48:43.081140", "string": "Test2", "uid": "e41ac05f-6c93-40c8-add6-90bccf8ab80d" } } }
然后修改规则为:
{ "rules": { "items": { "$noteId": { ".read": "data.child('uid').val() === auth.uid", ".write": "newData.child('uid').val() === auth.uid" }, ".indexOn": ["modifiedAt", "uid"] } } }
2. 模拟请求的路径错误
你在Rules Playground中模拟的请求路径是/item,但你的实际数据和规则都是针对/items(复数形式)的,这也是导致读取被拒的直接原因。请将模拟请求的路径改为/items,如果是读取单个笔记则改为/items/-MwtOrIBmhaoiGtSjzRl。
3. 开放权限规则依然无效的原因
即使你设置了".read": true,但因为请求路径错误(/item而非/items),规则中items节点的权限不会作用到不存在的item节点,所以依然会被拒绝。修正路径后,开放权限的规则就能正常通过模拟。
最后提醒:在实际代码中,用户登录后读取数据的路径要和规则、数据库结构对应,比如用解决方案A的话,读取路径应为items/{currentUser.uid},这样才能正确触发权限校验逻辑。
内容的提问来源于stack exchange,提问作者Joey Hwang

