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

Flutter中如何获取Firebase Realtime Database规则触发的报错

解决方案

你无法捕获规则报错主要是三个核心问题:

  • 匿名用户分支的数据库写入逻辑没有包裹异常捕获逻辑
  • 异步方法updateDisplayName没有加await,执行时序错误
  • 异常捕获的类型匹配错误,新版FlutterFire Realtime Database抛出的异常为FirebaseException而非旧的DatabaseError

修复步骤

  1. 给匿名用户分支的逻辑也加上try-catch包裹
  2. 给所有异步的用户更新、数据库写入方法加上await修饰
  3. 调整异常捕获的类型优先级,优先捕获FirebaseException
  4. 补全函数的返回值,符合声明的返回类型

修复后的完整代码

import 'package:firebase_core/firebase_core.dart' show FirebaseException; // 需提前导入对应头文件

Future<User?> addUsernameToDatabase(String? username) async {
  final user = FirebaseAuth.instance.currentUser;
  if(user == null || username == null) return null;
  setLoading(true);
  try {
    // 异步方法必须加await等待执行完成
    await user.updateDisplayName(username);
    final uid = user.uid;
    if(user.isAnonymous) {
      print("Guest user");
      await _dbRef.child('usernames').child(username).set(uid);
    } else {
      await _dbRef.child('usernames').child(username).set(uid);
    }
    setLoading(false);
    return user;
  } on FirebaseException catch (error) {
    // 规则拦截的报错会在这里捕获,错误code为permission-denied
    print("数据库规则拦截错误:${error.code},信息:${error.message}");
    setLoading(false);
    return null;
  } on PlatformException catch (error) {
    print("平台错误:${error.toString()}");
    setLoading(false);
    return null;
  } catch (error) {
    print("未知错误:${error.toString()}");
    setLoading(false);
    return null;
  }
}

额外补充

你当前贴出的数据库规则仅校验了/users/$uid/username节点的写入合法性,并没有对/usernames节点的写入做限制。如果需要保证/usernames节点下的用户名全局唯一,需要补充对应规则:

{
  "rules": {
    "usernames": {
      "$username": {
        ".write": "!data.exists() || data.val() === auth.uid"
      }
    },
    // 剩下的原有规则保持不变
    ".read": true,
    ".write": true,
    "users":{
      "$uid": {
        ".write": "auth !== null && auth.uid === $uid",
        ".read": "auth !== null && auth.provider === 'password'",
        "username": {
          ".validate": "!root.child('usernames').child(newData.val()).exists() || root.child('usernames').child(newData.val()).val() == $uid"
        }
      }
    }
  }
}

修复完成后规则触发的权限拒绝错误就会被FirebaseException正常捕获,你可以根据error.code == 'permission-denied'判断是用户名重复导致的拦截,给用户弹出对应提示即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 04:45:02