持久化用户身份验证 Flutter Firebase
Posted
技术标签:
【中文标题】持久化用户身份验证 Flutter Firebase【英文标题】:Persist user Auth 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 发布了代码。 【参考方案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();
【讨论】:
以上是关于持久化用户身份验证 Flutter Firebase的主要内容,如果未能解决你的问题,请参考以下文章
Flutter Firebase auth 用户在设备上不是持久的
如何在 Flutter 应用程序中更新 Firebase 令牌并存储它?
如何在启用电话身份验证的情况下导出 Firebase 用户帐户