You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Firebase Auth登出触发权限拒绝错误的解决求助

Firebase Auth登出后触发Firebase Database权限拒绝错误的解决方法

我在使用Firebase Auth执行登出操作时遇到了权限拒绝错误,相关代码及错误信息如下:

登出代码

onPressed: () async {
  await FirebaseAuth.instance.signOut();
  await widget.checkLogin();
},

CheckLogin函数

checkLogin() async {
  if (FirebaseAuth.instance.currentUser != null) {
    login = true;
    setState(() {});
  } else {
    login = false;
    setState(() {});
  }
}

错误信息

Unhandled Exception: [firebase_database/permission-denied] Client doesn't have permission to access the desired data.

经过排查,问题出在以下代码片段,但我不知道如何修复:

if (FirebaseAuth.instance.currentUser != null) {
  WidgetsBinding.instance.addPostFrameCallback((_) async {
    DatabaseReference ref = FirebaseDatabase.instance.ref("temp");
    if (FirebaseAuth.instance.currentUser != null) {
      ref.onValue.listen((DatabaseEvent event) {
        final snapshot = event.snapshot.value;
        if (snapshot != null) {
          Object? temp = snapshot;

          if (mounted) {
            setState(() {});
          }
        }
      });
    }
  });
}

问题根源

你添加的ref.onValue.listen是一个实时监听,用户登出后这个监听并不会自动停止。当Firebase Auth身份凭证失效后,监听仍会尝试请求temp节点数据,触发数据库权限校验,最终导致权限拒绝错误。

修复步骤

  1. 保存监听订阅对象:创建监听时,把返回的StreamSubscription对象保存下来,用于后续取消操作。
  2. 登出时主动取消监听:执行signOut前先取消监听,避免无权限请求继续发送。
  3. 组件销毁时取消监听:防止内存泄漏,同时避免组件销毁后监听仍运行引发错误。

修改后的代码示例

首先在State类中添加订阅变量:

StreamSubscription<DatabaseEvent>? _tempSubscription;

修改监听代码,保存订阅对象:

if (FirebaseAuth.instance.currentUser != null) {
  WidgetsBinding.instance.addPostFrameCallback((_) async {
    DatabaseReference ref = FirebaseDatabase.instance.ref("temp");
    if (FirebaseAuth.instance.currentUser != null) {
      _tempSubscription = ref.onValue.listen((DatabaseEvent event) {
        final snapshot = event.snapshot.value;
        if (snapshot != null) {
          Object? temp = snapshot;

          if (mounted) {
            setState(() {});
          }
        }
      });
    }
  });
}

更新登出方法,先取消监听:

onPressed: () async {
  _tempSubscription?.cancel();
  _tempSubscription = null;
  await FirebaseAuth.instance.signOut();
  await widget.checkLogin();
},

最后在组件销毁时补充取消逻辑(推荐):

@override
void dispose() {
  _tempSubscription?.cancel();
  super.dispose();
}

额外提示

  • 你的数据库规则限制认证用户访问temp节点是合理的安全设置,无需修改规则。
  • 不要仅依赖currentUser != null的判断避免错误,异步场景下身份状态可能在判断后变化,主动取消监听才是可靠方案。

内容的提问来源于stack exchange,提问作者Jonathan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 19:45:40