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

Flutter接入Firebase Auth时未验证邮箱用户仍可访问应用如何解决

解决方案

1. 扩展用户模型

首先给你的Users类新增isEmailVerified字段,用于存储邮箱验证状态:

class Users {
  final String uid;
  final bool isEmailVerified; // 新增字段
  Users({required this.uid, required this.isEmailVerified});
}

2. 调整AuthService逻辑

需要做三处核心修改:

  • 修改用户数据转换方法,带入验证状态
  • 注册成功后自动发送验证邮件
  • 替换监听流为userChanges()(authStateChanges仅监听登录/登出状态变化,不会同步邮箱验证状态的更新)
  • 新增刷新用户验证状态、重发验证邮件的工具方法

修改后的AuthService代码:

class AuthService {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final googleSignIn = GoogleSignIn();

  GoogleSignInAccount? _user;

  // 修改用户转换方法,带入验证状态
  Users? _userFromFirebaseUser(User? user) {
    return user != null ? Users(uid: user.uid, isEmailVerified: user.emailVerified) : null;
  }

  // 替换为userChanges流,可监听邮箱验证状态更新
  Stream<Users?> get user {
    return _auth.userChanges().map(_userFromFirebaseUser);
  }

  //注册 with 邮箱&密码
  Future registerWithEmailAndPassword(String email, String password) async {
    try {
      UserCredential result = await _auth.createUserWithEmailAndPassword(
          email: email, password: password);
      User? user = result.user;
      if (user != null && !user.emailVerified) {
        // 注册成功后自动发送验证邮件
        await user.sendEmailVerification();
      }
      return _userFromFirebaseUser(user);
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  // 新增:刷新用户验证状态(用户点击验证链接回到APP后调用)
  Future reloadUser() async {
    try {
      await _auth.currentUser?.reload();
    } catch (e) {
      print(e.toString());
    }
  }

  // 新增:重发验证邮件
  Future resendVerificationEmail() async {
    try {
      await _auth.currentUser?.sendEmailVerification();
    } catch (e) {
      print(e.toString());
    }
  }

  //sign out
  Future signOut() async {
    try {
      return await _auth.signOut();
    } catch (e) {
      print(e.toString());
      return null;
    }
  }
}

3. 修改Wrapper路由判断逻辑

在原有登录状态判断的基础上,新增邮箱验证状态判断,未验证的用户跳转至验证提示页:

class Wrapper extends StatelessWidget {
  const Wrapper({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final user = Provider.of<Users?>(context);

    if (user == null) {
      // 未登录跳转认证页
      return Authenticate();
    } else if (!user.isEmailVerified) {
      // 已登录但未验证邮箱,跳转验证提示页
      return EmailVerificationPage();
    } else {
      // 验证通过跳转首页
      return Home();
    }
  }
}

4. 实现邮箱验证提示页

新增EmailVerificationPage组件,提示用户查收验证邮件,同时提供重发邮件、手动刷新验证状态的按钮:

class EmailVerificationPage extends StatelessWidget {
  final AuthService _auth = AuthService();
  EmailVerificationPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text("我们已向你的注册邮箱发送了验证链接,请点击链接完成验证后再进入应用"),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                await _auth.reloadUser();
              },
              child: const Text("我已完成验证,刷新状态"),
            ),
            TextButton(
              onPressed: () async {
                await _auth.resendVerificationEmail();
                ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("验证邮件已重发")));
              },
              child: const Text("没收到邮件?重发验证链接"),
            ),
            TextButton(
              onPressed: () async {
                await _auth.signOut();
              },
              child: const Text("换个邮箱注册"),
            )
          ],
        ),
      ),
    );
  }
}

5. 后端安全加固

前端逻辑仅用于用户体验优化,必须同步配置Firebase安全规则,阻止未验证邮箱的用户访问后端资源,示例规则参考:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null && request.auth.token.email_verified == true;
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 05:45:03