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

Flutter中如何将Firebase Auth用户删除与Firestore更新纳入同一事务?

在Flutter Firebase中实现Auth删用户与Firestore更新的原子性操作

Firebase Auth的用户删除操作无法直接纳入Firestore事务——因为Firestore事务仅对Firestore内部的读写操作生效,Auth是独立服务,不支持跨服务事务机制。要实现近似原子性的操作,需采用先更新Firestore、再删除Auth用户的顺序,并添加失败回滚逻辑,最大程度保证操作一致性。

实现思路

  1. 用Firestore事务将用户文档标记为已删除,确保更新操作的原子性
  2. 尝试删除Auth用户账号
  3. 若Auth删除失败,立即回滚Firestore的标记状态
  4. 处理requires-recent-login异常,重新验证后重试完整流程

修改后的代码实现

/// 删除用户账号并同步标记Firestore文档
static Future<void> deleteUserAccount(shokaze.User user) async {
  final firestore = FirebaseFirestore.instance;
  bool firestoreMarkedDeleted = false;

  try {
    // 第一步:通过Firestore事务标记用户为已删除
    await firestore.runTransaction((transaction) async {
      final userDoc = firestore.collection(user.collectionName).doc(user.id);
      final docSnapshot = await transaction.get(userDoc);
      
      if (!docSnapshot.exists) {
        throw Exception("用户文档不存在");
      }

      transaction.update(userDoc, {"deleted": true});
      firestoreMarkedDeleted = true;
    });

    // 第二步:删除Auth用户账号
    await _auth.currentUser!.delete();
  } on FirebaseAuthException catch (e) {
    debugPrint("删除Auth用户出错: $e");

    // 回滚Firestore的删除标记
    if (firestoreMarkedDeleted) {
      await firestore.collection(user.collectionName).doc(user.id).update({"deleted": false});
    }

    if (e.code == "requires-recent-login") {
      // 重新验证后重试完整删除流程
      await _reauthenticateAndDelete(user);
    } else {
      // 处理其他Auth异常
      rethrow;
    }
  } catch (e) {
    debugPrint("删除用户过程出错: $e");

    // 回滚Firestore标记(如果已完成标记)
    if (firestoreMarkedDeleted) {
      await firestore.collection(user.collectionName).doc(user.id).update({"deleted": false});
    }

    rethrow;
  }
}

/// 重新验证用户并执行删除流程
static Future<void> _reauthenticateAndDelete(shokaze.User user) async {
  // 此处添加你的重新验证逻辑,比如获取用户输入的密码生成Auth凭证
  // 示例:final credential = EmailAuthProvider.credential(email: user.email, password: inputPassword);

  try {
    await _auth.currentUser!.reauthenticateWithCredential(credential);
    // 重新执行完整删除流程
    await deleteUserAccount(user);
  } catch (e) {
    debugPrint("重新验证并删除出错: $e");
    // 回滚Firestore标记
    await FirebaseFirestore.instance.collection(user.collectionName).doc(user.id).update({"deleted": false});
    rethrow;
  }
}

补充说明

  • 这种方案能最大程度保证操作一致性,先完成Firestore的原子更新,再执行Auth删除;若Auth操作失败,立刻回滚Firestore状态
  • 极端场景下(如Firebase服务突然中断)仍可能出现状态不一致,可考虑添加定时校验任务清理这类异常数据
  • Firestore事务确保标记删除操作是原子的,不会出现文档部分更新的情况

内容的提问来源于stack exchange,提问作者Stéphane de Luca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 22:12:50