【问题标题】:Persist user Auth Flutter Firebase持久化用户身份验证 Flutter Firebase
【发布时间】:2019-06-25 10:08:02
【问题描述】:

我在 Flutter 中使用 Firebase Auth 和谷歌登录。我可以登录,但是当我关闭应用程序(杀死它)时,我必须重新注册。那么有没有办法保持用户身份验证直到用户特别注销? 这是我的身份验证课程

import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

class Auth {
  FirebaseAuth _firebaseAuth;
  FirebaseUser _user;

  Auth() {
    this._firebaseAuth = FirebaseAuth.instance;
  }

  Future<bool> isLoggedIn() async {
    this._user = await _firebaseAuth.currentUser();
    if (this._user == null) {
      return false;
    }
    return true;
  }

  Future<bool> authenticateWithGoogle() async {
    final googleSignIn = GoogleSignIn();
    final GoogleSignInAccount googleUser = await googleSignIn.signIn();
    final GoogleSignInAuthentication googleAuth =
    await googleUser.authentication;
    this._user = await _firebaseAuth.signInWithGoogle(
      accessToken: googleAuth.accessToken,
      idToken: googleAuth.idToken,
    );
    if (this._user == null) {
      return false;
    }
    return true;
    // do something with signed-in user
  }
}

这是我调用身份验证检查的起始页面。

import 'package:flutter/material.dart';
import 'auth.dart';
import 'login_screen.dart';
import 'chat_screen.dart';

class Splash extends StatefulWidget {

  @override
  _Splash createState() => _Splash();
}

class _Splash extends State<Splash> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: CircularProgressIndicator(
          value: null,
        ),
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    _handleStartScreen();
  }

  Future<void> _handleStartScreen() async {
    Auth _auth = Auth();
    if (await _auth.isLoggedIn()) {
      Navigator.of(context).pushReplacementNamed("/chat");
    }
    Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) => LoginScreen(auth: _auth,)));
  }
}

【问题讨论】:

  • ????您可以添加用于登录的代码吗?通常你不需要坚持任何事情来实现这一点 - 它只是工作。添加您检测到用户已经登录的代码。它可能是您的路由逻辑中的一个问题。
  • 我在应用启动时运行 isLoggedIn() 来决定是从登录屏幕还是主屏幕启动。
  • @Feu 发布了代码。

标签: firebase flutter firebase-authentication


【解决方案1】:

我相信你的问题是路由。在我的应用程序中,我使用FirebaseAuth,它就像你说的那样工作,而且我不保留任何登录令牌。但是,我不知道为什么您使用 getUser 的方法不起作用。

尝试调整您的代码以使用onAuthStateChanged

基本上,在您的MaterialApp 上,创建一个StreamBuilder 监听_auth.onAuthStateChanged 并根据身份验证状态选择您的页面。

我将复制并粘贴我的应用程序的部分内容,以便您有所了解:

[...]

final FirebaseAuth _auth = FirebaseAuth.instance;

Future<void> main() async {
  FirebaseApp.configure(
    name: '...',
    options:
      Platform.isIOS
        ? const FirebaseOptions(...)
        : const FirebaseOptions(...),
    );

  [...]  

  runApp(new MaterialApp(
    title: '...',
    home: await getLandingPage(),
    theme: ThemeData(...),
  ));
}

Future<Widget> getLandingPage() async {
  return StreamBuilder<FirebaseUser>(
    stream: _auth.onAuthStateChanged,
    builder: (BuildContext context, snapshot) {
      if (snapshot.hasData && (!snapshot.data.isAnonymous)) {
        return HomePage();
      }

      return AccountLoginPage();
    },
  );
}

【讨论】:

  • 我添加了我正在检查已登录用户以路由到正确页面的主页。
  • 不要像现在这样进行检查,使用 OnAuthStateChanged!
  • 好的。我会去做。另外,你能告诉我这种方法出了什么问题吗?我想知道。
  • 也许在您请求的那一刻,有关已登录用户的信息不可用 - 但这只是一个理论。在收听 onAuthStateChange 时,也许该信息稍后会变得可用,然后您就可以捕捉到它。或者也许这只是一个错误! ? 作为此更改的一个很好的副作用,当您调用 _auth 注销方法时,此流也会触发该更改,将页面更改为自动登录!
  • 太棒了!因为它正在工作,你能接受它作为答案吗?
【解决方案2】:

对不起,这是我的错误。忘记把推送登录界面放在else里了。

  Future<void> _handleStartScreen() async {
    Auth _auth = Auth();
    if (await _auth.isLoggedIn()) {
      Navigator.of(context).pushReplacementNamed("/chat");
    }
    else {
        Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) => LoginScreen(auth: _auth,)));
    }
  }

【讨论】:

  • 是的,至少现在我知道这不是 firebase 错误。
【解决方案3】:
void main() {
FirebaseAuth.instance.authStateChanges().listen((User user) {
  if (user == null) {
          runApp(MyApp(auth : false);
        } else {
          runApp(MyApp(auth : false);
       }
    });
}

class MyApp extends StatefulWidget {
  final bool auth;
  MyApp({this.auth});
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  return MaterialApp(
  ......
  ......
  home: widget.auth ? MainScreen() : AuthScreen();
);

【讨论】:

    【解决方案4】:

    您可以使用shared_preferences 使您的会话保持活跃,即使您终止了应用程序。 这是文档https://pub.dartlang.org/packages/shared_preferences

    我还听说可以使用 sqlite 来保持会话。

    【讨论】:

    • 但是在 sqllite 中存储什么。另外我正在尝试制作一个聊天应用程序,因此它需要保持授权才能获得新的通知。
    • 通常你存储用户的信息,但我认为令牌是最重要的存储。
    • 好的,我试试看。
    • 我希望你能成功!祝你好运!。
    【解决方案5】:

    添加此代码。它应该可以正常工作。

    FirebaseAuth auth = FirebaseAuth.instance;
    
    auth.setPersistence(Persistence.SESSION);
    

    【讨论】:

    • 未处理异常:UnimplementedError:setPersistence() 仅在基于 Web 的平台上受支持
    • @nadeesh 试试这个:if(kIsWeb) auth.setPersistence(Persistence.SESSION);
    • 请查看文档,它仅适用于基于 Web 的平台。
    【解决方案6】:

    你可以使用我的代码,你可以使用 userChanges() 代替 authStateChanges()

    通知任何用户更新的更改。

    这是 [authStateChanges] 和 [idTokenChanges] 的超集。它提供有关所有用户更改的事件,例如何时链接、取消链接凭据以及何时更新用户配置文件。此 Stream 的目的是侦听用户状态的实时更新(登录、退出、不同用户和令牌刷新),而无需手动调用 [reload] 然后重新对您的应用程序所做的更改。

    final Stream<User?> firebaseUserChanges = firebaseAuth.userChanges();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-04
      • 1970-01-01
      • 2016-10-20
      相关资源
      最近更新 更多