使用Firebase进行声明式身份验证路由 [英] Declarative auth routing with Firebase
问题描述
我没有使用 Navigator.push
来使用户登录或注销,而是一直使用流来侦听登录和注销事件.
Rather than pushing the user around with Navigator.push
when they sign in or out, I've been using a stream to listen for sign in and sign out events.
StreamProvider<FirebaseUser>.value(
value: FirebaseAuth.instance.onAuthStateChanged,
)
它对于本地路由非常有用,因为它可以立即处理仍在通过身份验证的用户登录.
It works great for the home route as it handles logging in users immediately if they're still authed.
Consumer<FirebaseUser>(
builder: (_, user, __) {
final isLoggedIn = user != null;
return MaterialApp(
home: isLoggedIn ? HomePage() : AuthPage(),
// ...
);
},
);
但是,这仅适用于本国路线.例如,如果用户随后导航到设置页面,然后单击按钮以注销,则不会以编程方式注销并再次跳转到身份验证屏幕.我要么不得不说 Navigator.of(context).pushNamedAndRemoveUntil('/auth',(_)=>假)
,要么会得到关于 user
为空的错误.
However, that's just for the home route. For example, if the user then navigates to a settings page where they click a button to sign out, there's no programmatic logging out and kicking to the auth screen again. I either have to say Navigator.of(context).pushNamedAndRemoveUntil('/auth', (_) => false)
or get an error about user
being null.
这很有道理.我只是在寻找另一种可能的方式,当他们注销时,我自己不必进行任何堆栈管理.
This makes sense. I'm just looking for possibly another way that when they do get logged out I don't have to do any stack management myself.
通过将 builder
属性添加到 MaterialApp
builder: (_, widget) {
return isLoggedIn ? widget : AuthPage();
},
这使我在未经身份验证后成功地将我移动到身份验证页面,但事实证明, widget
实际上是导航器.这意味着当我回到 AuthPage
时,我无法调用依赖于父级导航器的任何内容.
This successfully moved me to the auth page after I was unauthenticated but as it turns out, widget
is actually the Navigator. And that means when I went back to AuthPage
I couldn't call anything that relied on a parent Navigator.
推荐答案
我找到了一种方法来完成此任务(LoVe的最佳答案仍然完全有效),以防其他任何人涉足此问题:
I found a way to accomplish this (LoVe's great answer is still completely valid) in case anyone else steps on this issue:
您需要利用嵌套的导航器. Root
将是内部导航器,外部导航器由 MaterialApp
创建:
You'll need to take advantage of nested navigators. The Root
will be the inner navigator and the outer navigator is created by MaterialApp
:
return MaterialApp(
home: isLoggedIn ? Root() : AuthPage(),
routes: {
Root.routeName: (_) => Root(),
AuthPage.routeName: (_) => AuthPage(),
},
);
您的 Root
将保存已认证用户的导航
Your Root
will hold the navigation for an authed user
class Root extends StatefulWidget {
static const String routeName = '/root';
@override
_RootState createState() => _RootState();
}
class _RootState extends State<Root> {
final _appNavigatorKey = GlobalKey<NavigatorState>();
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
final canPop = _appNavigatorKey.currentState.canPop();
if (canPop) {
await _appNavigatorKey.currentState.maybePop();
}
return !canPop;
},
child: Navigator(
initialRoute: HomePage.routeName,
onGenerateRoute: (RouteSettings routeSettings) {
return MaterialPageRoute(builder: (_) {
switch (routeSettings.name) {
case HomePage.routeName:
return HomePage();
case AboutPage.routeName:
return AboutPage();
case TermsOfUsePage.routeName:
return TermsOfUsePage();
case SettingsPage.routeName:
return SettingsPage();
case EditorPage.routeName:
return EditorPage();
default:
throw 'Unknown route ${routeSettings.name}';
}
});
},
),
);
}
}
现在,您可以在设置页面(或任何其他页面)内取消身份验证( FirebaseAuth.instance.signout()
),然后立即被踢出auth页面,而无需调用 Navigator
方法.
Now you can unauthenticate (FirebaseAuth.instance.signout()
) inside of the settings page (or any other page) and immediately get kicked out to the auth page without calling a Navigator
method.
这篇关于使用Firebase进行声明式身份验证路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!