Android Studio Firebase Realtime Database删除数据始终被拒如何解决
Firebase数据库删除用户数据被权限拒绝解决方案
问题现象
每次尝试从数据库删除用户数据时操作都会被拒绝,当前规则配置下可以正常执行创建、读取、更新操作,仅删除失败,只有将规则设置为.write: true时才能正常删除。
现有配置
数据库安全规则
{ "rules": { "admin": { ".read": "true", ".write": "auth != null" }, "products": { ".read": "auth != null", ".write": "auth != null" }, "users": { ".read": "root.child('users').child(auth.uid).child('account_role').val() == 'admin'", ".write": "root.child('users').child(auth.uid).child('account_role').val() == 'admin'", "$uid": { ".read": "auth.uid == $uid", ".write": "auth.uid == $uid" } } } }
删除操作代码
databaseReference = FirebaseDatabase.getInstance().getReference("users").child(userUid); databaseReference.removeValue().addOnSuccessListener(unused -> Log.d(TAG, getString(R.string.data_successful_deleted))).addOnFailureListener(e -> { Log.d(TAG, e.getMessage()); Toast.makeText(DeleteAccountActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show(); });
数据库结构
问题原因
90%以上的同类问题都是操作顺序错误:
- 注销/删除账号时如果先调用Firebase Auth的
delete()方法删除认证账号,认证凭证会立刻失效,后续执行数据库删除操作时auth对象为null,规则auth.uid == $uid会直接判定为false,返回权限拒绝。 - 创建、更新操作可以正常执行,是因为执行这些操作时用户仍处于有效登录状态,认证信息未失效。
剩下的小概率原因是规则逻辑未覆盖删除场景:父节点users的写权限仅开放给管理员,普通用户对自身$uid节点的写权限虽然理论上会生效,但部分SDK版本下删除整节点时会额外校验父节点权限,导致拦截。
修复方案
第一步:调整操作顺序
严格按照「先删数据库数据,再删认证账号」的顺序执行注销逻辑,示例代码:
// 1. 先删除数据库中的用户节点 databaseReference.removeValue().addOnSuccessListener(unused -> { Log.d(TAG, getString(R.string.data_successful_deleted)); // 2. 数据库删除成功后,再删除Auth认证账号 FirebaseAuth.getInstance().getCurrentUser().delete().addOnSuccessListener(unused1 -> { // 注销完成后的跳转、提示逻辑 }); }).addOnFailureListener(e -> { Log.d(TAG, e.getMessage()); Toast.makeText(DeleteAccountActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show(); });
第二步:优化安全规则
调整users节点下的规则,显式授予普通用户删除自身节点的权限,同时增加校验防止普通用户越权修改自己的角色,修改后规则如下:
{ "rules": { "admin": { ".read": "true", ".write": "auth != null" }, "products": { ".read": "auth != null", ".write": "auth != null" }, "users": { "$uid": { ".read": "auth.uid == $uid || (auth != null && root.child('users').child(auth.uid).child('account_role').val() == 'admin')", ".write": "auth.uid == $uid || (auth != null && root.child('users').child(auth.uid).child('account_role').val() == 'admin')", // 禁止普通用户篡改自身账号角色,删除操作(newData不存在)不受该规则限制 ".validate": "!newData.exists() || (auth.uid == $uid && (!newData.hasChild('account_role') || newData.child('account_role').val() == data.child('account_role').val())) || root.child('users').child(auth.uid).child('account_role').val() == 'admin'" } } } }
注意:原规则中
users根节点的读写权限仅开放给管理员,会导致普通用户无法查询用户列表,如果没有开放用户列表的需求可以保留该逻辑,如果需要可以根据业务场景调整。
内容的提问来源于stack exchange,提问作者Vinicius Cavalcante de Moura
相关产品推荐
相关产品推荐

