使用 Flutter Web 刷新后如何维护 Firebase 身份验证?

Art*_*xha 6 firebase firebase-authentication flutter-web flutter-provider

我正在使用来自 Firebase 的 authStateChanges 流和 flutter。我有两种视图,一种用于移动设备,另一种用于 Web 应用程序。如果用户未连接、登录或通过身份验证,我想将用户重定向到登录屏幕。起初它运行良好,但当我登录并刷新浏览器时,我加载登录屏幕大约 1 秒,然后再次出现 Web 屏幕。我用 print 检查了发生的情况,从我所看到的情况来看,authStateChanges Stream 在 1-2 秒内为空(当登录屏幕出现时),然后当流接收到连接的用户时有一个值。有没有办法检查或等到身份验证完成后再加载登录屏幕(当它不能加载它时)?

我的主要组件包含 StreamBuilder 如下:

  Widget build(BuildContext context) {
    final firebaseAuthService = Provider.of<FirebaseAuthService>(context);
    return StreamBuilder<User>(
        stream: firebaseAuthService.authStateChanges(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.active) {
            User user = snapshot.data;
            if (user == null) {
              //first time no connection
              return SignIn();
            }
            if (kIsWeb) {
              return WebMain(user: user);
            }
            // load mobile version
            return MobileMain();
          }
          return Scaffold(
            body: Center(
              child: CircularProgressIndicator(),
            ),
          );

        });
  }

Run Code Online (Sandbox Code Playgroud)

在这里您可以找到我的 FirebaseAuth 包装类,其中包含来自 firebase 的方法:

class FirebaseAuthService {
  final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
  User _user;
  bool get isAuthenticated {
    return _user == null ? false : true;
  }
  User get user {
    return _user;
  }
  Future<User> signInWithEmailAndPassword(
      String userEmail, String userPassword) async {
    return _user = await _firebaseAuth
        .signInWithEmailAndPassword(email: userEmail, password: userPassword)
        .then((userCredential) => userCredential.user);
  }
  Stream<User> authStateChanges() {
    _user = _firebaseAuth.currentUser;
    return _firebaseAuth.authStateChanges();
  }
  Future<void> signOut() async {
    return _firebaseAuth.signOut();
  }
}

Run Code Online (Sandbox Code Playgroud)

Fri*_*yan 4

虽然我不确定为什么 authStateChanges 在用户登录状态更改时(通常是一秒钟后)不通知,但类似的功能似乎确实适合您的用例。

尝试 idTokenChanges()

  FirebaseAuth.instance.idTokenChanges().listen((event) {
    print("On Data: ${event}");
  });
Run Code Online (Sandbox Code Playgroud)

此事件将返回您的 Firebase User 对象。刷新时,它最初可能返回“null”,但在一秒钟内,返回您登录的用户。您可以让登录页面等待几秒钟,以确保登录的用户没有被初始化。

编辑:虽然可能有更好的解决方案,但这目前对我有用。

  final subscription = FirebaseAuth.instance.idTokenChanges().listen(null);
  subscription.onData((event) async {

    if(event != null) {
      print("We have a user now");
      isLoading = false;
      print(FirebaseAuth.instance.currentUser);
      subscription.cancel();

      Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => OverviewController())
      );

    } else {
      print("No user yet..");
      await Future.delayed(Duration(seconds: 2));
      if(isLoading) {
        Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => LoginController())
        );

        isLoading = false;
        subscription.cancel();
      }
    }
  });
Run Code Online (Sandbox Code Playgroud)