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

如何在Flutter中集成Firebase邮箱验证,实现用户注册后需验证邮箱才可登录

Flutter Firebase 邮箱验证功能实现代码

核心逻辑:用户注册成功后不直接进入系统,先触发验证邮件发送,仅当用户点击邮箱内的验证链接完成校验后,才可正常登录。

1. 修改注册逻辑(registerNewUser方法)

创建账号成功后,立刻发送验证邮件,存储用户基础信息后跳转至邮箱验证提示页,不直接进入主页。

final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;

void registerNewUser(BuildContext context) async {
  showDialog(
    context: context,
    barrierDismissible: false,
    builder: (BuildContext context) {
      return ProgressDialog(message: "注册中,请稍候....",);
    });

  try {
    final UserCredential userCredential = await _firebaseAuth.createUserWithEmailAndPassword(
      email: emailTextEditingController.text.trim(),
      password: passwordTextEditingController.text.trim(),
    );
    final User? firebaseUser = userCredential.user;

    if (firebaseUser != null) {
      // 发送验证邮件
      await firebaseUser.sendEmailVerification();
      // 存储用户基础信息
      Map userDataMap = {
        "name": nameTextEditingController.text.trim(),
        "email": emailTextEditingController.text.trim(),
        "phone": phoneTextEditingController.text.trim(),
        "isVerified": false, // 可选:存储验证状态方便后续查询
      };
      await usersRef.child(firebaseUser.uid).set(userDataMap);
      Navigator.pop(context); // 关闭加载弹窗
      displayToastMessage("验证邮件已发送至你的邮箱,请完成验证后登录", context);
      // 跳转至验证提示页,不要直接进主页
      Navigator.pushNamedAndRemoveUntil(context, EmailVerifyScreen.idscreen, (route) => false);
    } else {
      Navigator.pop(context);
      displayToastMessage("用户账号创建失败,请重试", context);
    }
  } catch (errMsg) {
    Navigator.pop(context);
    displayToastMessage("错误:${errMsg.toString()}", context);
  }
}

2. 新增邮箱验证等待页示例

该页面用于提示用户查收邮件,提供刷新验证状态、重发验证邮件的能力,检测到验证通过后跳转至主页。

class EmailVerifyScreen extends StatefulWidget {
  static const idscreen = "EmailVerifyScreen";
  const EmailVerifyScreen({super.key});

  @override
  State<EmailVerifyScreen> createState() => _EmailVerifyScreenState();
}

class _EmailVerifyScreenState extends State<EmailVerifyScreen> {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  Timer? _timer;

  @override
  void initState() {
    super.initState();
    // 定时刷新用户验证状态
    _timer = Timer.periodic(const Duration(seconds: 3), (timer) async {
      await _auth.currentUser?.reload();
      if (_auth.currentUser?.isEmailVerified == true) {
        timer.cancel();
        // 更新数据库里的验证状态
        await usersRef.child(_auth.currentUser!.uid).update({"isVerified": true});
        displayToastMessage("邮箱验证成功", context);
        Navigator.pushNamedAndRemoveUntil(context, MainScreen.idscreen, (route) => false);
      }
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text("验证邮件已发送,请点击邮箱内的链接完成验证", textAlign: TextAlign.center, style: TextStyle(fontSize: 18)),
            const SizedBox(height: 30),
            ElevatedButton(
              onPressed: () async {
                // 手动刷新验证状态
                await _auth.currentUser?.reload();
                if (_auth.currentUser?.isEmailVerified == true) {
                  await usersRef.child(_auth.currentUser!.uid).update({"isVerified": true});
                  if (!mounted) return;
                  displayToastMessage("邮箱验证成功", context);
                  Navigator.pushNamedAndRemoveUntil(context, MainScreen.idscreen, (route) => false);
                } else {
                  displayToastMessage("尚未完成验证,请查收邮箱点击链接", context);
                }
              },
              child: const Text("我已完成验证,刷新状态"),
            ),
            TextButton(
              onPressed: () async {
                // 重发验证邮件
                await _auth.currentUser?.sendEmailVerification();
                displayToastMessage("验证邮件已重新发送", context);
              },
              child: const Text("没收到邮件?重新发送"),
            ),
            TextButton(
              onPressed: () {
                _auth.signOut();
                Navigator.pushNamedAndRemoveUntil(context, LoginScreen.idscreen, (route) => false);
              },
              child: const Text("返回登录页"),
            )
          ],
        ),
      ),
    );
  }
}

3. 登录页增加验证状态校验

登录时必须判断邮箱是否已验证,未验证的用户禁止进入系统:

// 登录按钮点击逻辑示例
onPressed: () async {
  // 省略原有表单校验逻辑
  try {
    final UserCredential userCredential = await _firebaseAuth.signInWithEmailAndPassword(
      email: emailController.text.trim(),
      password: passwordController.text.trim(),
    );
    final User? user = userCredential.user;
    if (user != null) {
      if (user.isEmailVerified) {
        // 验证通过,进入主页
        Navigator.pushNamedAndRemoveUntil(context, MainScreen.idscreen, (route) => false);
      } else {
        await _firebaseAuth.signOut();
        displayToastMessage("请先完成邮箱验证后再登录", context);
        // 可跳转至验证等待页
        Navigator.pushNamed(context, EmailVerifyScreen.idscreen);
      }
    }
  } catch (e) {
    displayToastMessage("登录错误:${e.toString()}", context);
  }
}

注意事项

  • 调用sendEmailVerification前需要先在Firebase控制台开启邮箱登录认证方式
  • 每次获取最新验证状态前,必须调用currentUser?.reload()刷新用户信息,否则会一直返回注册时的初始状态
  • 验证邮件的模板可在Firebase控制台的认证设置中自定义

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.20 22:45:02