如何在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
相关产品推荐
相关产品推荐

