【问题标题】:Flutter Streambuilder not working as expected with FirebaseFlutter Streambuilder 在 Firebase 中无法正常工作
【发布时间】:2021-03-02 02:24:19
【问题描述】:

不确定我是否在考虑这个问题。据我所知,如果用户已从 Firebase 后端删除,则 Streambuilder 应该将您注销。

我现在正在做的步骤-

  1. 正在加载应用程序
  2. 登录应用
  3. 正在加载 firebase 并从后端删除已登录的用户。

我相信这样做也会让我退出应用程序。对吗?

这是我的代码 -

   void main() async {
    WidgetsFlutterBinding.ensureInitialized();
    await Firebase.initializeApp();
    runApp(MaterialApp(
        theme: ThemeData(
          accentColor: Colors.orange,
          primarySwatch: Colors.blue,
        ),
        home: StreamBuilder(
          stream: FirebaseAuth.instance.authStateChanges(),
          builder: (context, snapshot) {
            print(FirebaseAuth.instance.authStateChanges());
          if (snapshot.connectionState == ConnectionState.active) {
            var user = snapshot.data;
            if (user == null) {
              return Welcome();
            }
            return Conversations("Logged in");
          }
        )
    ));
  }

【问题讨论】:

    标签: firebase flutter firebase-authentication


    【解决方案1】:

    Firebase 身份验证使用长期令牌和短期令牌的组合来管理登录会话,并且最长可能需要一个小时才能刷新短期令牌并且客户端检测到客户端已注销.

    如果您等待的时间不到一个小时,这可能是您的 authStateChanges() 没有使用新值触发的原因:令牌仍然有效,因此客户端的身份验证状态尚未更改。


    如果您想了解如何撤销用户的令牌,我建议您阅读that 上的文档。但公平的警告:这比在客户端上简单地登录和退出要复杂得多。


    如果您的目标是能够立即锁定用户,那么可能还有其他方法可以做到这一点。例如,在使用 Firebase 的实时数据库或 Firestore 时,通常会在数据库中保留“被阻止的 UID”列表,并在数据库的安全规则中检查该列表。

    【讨论】:

    • 感谢 Frank 的详细解释。
    【解决方案2】:

    使用signOut()注销时,状态会立即更新,但删除用户时可能不是这样。

    更改可能需要一段时间才能通知到前端的流。你可以在这里阅读更多内容:Firebase user deleted but still logged in on device

    Firebase 身份验证令牌的有效期为一小时,并缓存在用户的设备上。它由客户端 SDK 自动刷新。删除帐户并不会主动联系用户的所有设备来删除令牌。

    您可以使用提供的signOut() 方法尝试这个迷你登录应用:

    import 'package:flutter/material.dart';
    import 'package:firebase_auth/firebase_auth.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.indigo,
          ),
          home: MyApp(),
        );
      }
    }
    
    class LandingPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return StreamBuilder<User>(
          stream: FirebaseAuth.instance.authStateChanges(),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.active) {
              User user = snapshot.data;
              if (user == null) {
                return Welcome();
              }
              return Conversations();
            } else {
              return Scaffold(
                body: Center(
                  child: CircularProgressIndicator(),
                ),
              );
            }
          },
        );
      }
    }
    
    class Welcome extends StatelessWidget {
    
      Future<void> _signInAnonymously() async {
        try {
          await FirebaseAuth.instance.signInAnonymously();
        } catch (e) {
          print(e);
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('Sign in')),
          body: Center(
            child: RaisedButton(
              child: Text('Sign in anonymously'),
              onPressed: _signInAnonymously,
            ),
          ),
        );
      }
    }
    
    class Conversations extends StatelessWidget {
    
      Future<void> _signOut() async {
        try {
          await FirebaseAuth.instance.signOut();
        } catch (e) {
          print(e); // TODO: show dialog with error
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Home Page'),
            actions: <Widget>[
              FlatButton(
                child: Text(
                  'Logout',
                  style: TextStyle(
                    fontSize: 18.0,
                    color: Colors.white,
                  ),
                ),
                onPressed: _signOut,
              ),
            ],
          ),
        );
      }
    }
    

    【讨论】:

    • 感谢 Bach 提供了带有 signout() 方法的代码。这有助于即时测试。
    猜你喜欢
    • 2021-07-14
    • 2019-08-03
    • 2021-12-12
    • 2023-01-04
    • 2019-01-08
    • 2021-08-22
    • 2021-05-17
    • 2021-09-04
    相关资源
    最近更新 更多