【问题标题】:How to maintain Firebase Authentication after refresh with Flutter web?使用 Flutter Web 刷新后如何维护 Firebase 身份验证?
【发布时间】:2021-03-10 02:33:52
【问题描述】:

我正在使用来自 Firebase 的 authStateChanges 流。我有两个视图,一个用于移动设备,另一个用于 Web 应用程序。如果用户未连接、未登录或未通过身份验证,我想将用户重定向到登录屏幕。起初它运行良好,但是当我登录并刷新浏览器时,我加载了登录屏幕大约 1 秒钟,然后 Web 屏幕再次出现。我检查了 print 发生了什么,从我看到的情况来看,authStateChanges 流在 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(),
            ),
          );

        });
  }

在这里你可以找到我的 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();
  }
}

【问题讨论】:

标签: firebase firebase-authentication flutter-web flutter-provider


【解决方案1】:

对我来说,下面的代码似乎工作正常。尽管文档中有一条警告说“您不应使用此 getter 来确定用户的当前状态,而应使用 [authStateChanges]、[idTokenChanges] 或 [userChanges] 来订阅更新。”

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Diary Book',
      theme: ThemeData(
        visualDensity: VisualDensity.adaptivePlatformDensity,
        primarySwatch: Colors.green,
      ),
      home: (FirebaseAuth.instance.currentUser == null)
          ? LoginPage()
          : MainPage(),
    );
  }
}
   

使用上述代码我没有遇到任何问题。我会让你知道如果这样做。如果有人可以评论任何未来的错误,这可能会很棒

【讨论】:

    【解决方案2】:

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

    试试 idTokenChanges()

      FirebaseAuth.instance.idTokenChanges().listen((event) {
        print("On Data: ${event}");
      });
    

    此事件将返回您的 Firebase 用户对象。刷新时,它最初可能会返回“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();
          }
        }
      });
    

    【讨论】:

    • 基本上,将 .authStateChanges() 替换为 .idTokenChanges() 似乎是该错误的解决方法
    • 感谢您的回答,有时间我会试试的
    猜你喜欢
    • 2020-11-27
    • 2020-11-27
    • 1970-01-01
    • 2021-01-17
    • 2019-01-05
    • 2016-05-29
    • 1970-01-01
    • 2021-07-08
    • 2022-01-11
    相关资源
    最近更新 更多