我正在尝试将用户身份验证实施到我的 Flutter 应用程序中,该应用程序应该适用于 Android 和 iOS。
我使用 JWT 验证应用程序对服务器的请求,因此我在用户登录时向用户提供 JWT 令牌,应用程序将令牌安全地保存在设备上,然后使用该令牌与我的服务器进行通信.
当应用启动时,我运行主页,其中有一个 if 语句,如果没有令牌,应用会在安全存储中查找 JWT 令牌,应用会显示登录页面。
主页类:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.orange,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'App Title'),
routes: <String, WidgetBuilder>{
'/login': (BuildContext context) => new SignInPage(),
},
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
...
@override
Widget build(BuildContext context) {
storage.read(key: 'jwt_token').then((token) {
logger.d('MAIN APP GOT TOKEN: ' + token.toString());
if (token == null) {
Navigator.pushReplacementNamed(context, '/login');
}
});
return Scaffold(...);
}
}
我尝试了 Navigator.pushReplacementNamed
、Navigator.pushNamed
、Navigator.popAndPushNamed
...所有这些都让我进入了登录页面。所以没关系。我的问题是,它不能反过来工作。
当我登录成功(获得 JWT 令牌)时,我无法让应用返回主页。如果我重新启动应用程序,它会正确显示主页(因为现在安全存储中有一个 JWT),所以令牌检查工作正常。一定是从登录页面重新路由到主页。
登录页面片段:
if (serverResponse.containsKey('jwt_token')) {
await storage.write(
key: 'jwt_token', value: serverResponse['jwt_token']);
Navigator.pushReplacementNamed(context, '/');
我也尝试过 Navigator.pop
和 Navigator.pushNamed(context, '/')
、Navigator.pushNamedAndRemoveUntil(context, '/', (route) => false)
、Navigator.pushReplacementNamed(context, '/')
,但都没有奏效。
看起来页面正在改变,但它最终又变成了登录页面。当调用重新路由命令时,我检查了令牌是否已经在存储中。此外,我在主页中的令牌检查上方有一条调试消息,并且在登录后永远不会打印调试字符串,因此根本不会调用主页。
你发现我的代码有问题吗?我怎样才能让它工作?
答案 0 :(得分:0)
这里的问题是您正在检查主页 build
上的令牌。
因此,每次启动屏幕时,如果用户未登录,就会正确重定向到登录页面。
但是,由于您使用了 Navigator.pushReplacementNamed
,它将 home
从您的路由列表中删除,那么如果您尝试任何选项将路由列表移回,例如 {{1} },路线列表上没有家了。
所以你基本上有两种选择来处理,根据你想要的行为:
这是我在实践中看到的最常见的方法,您的第一个应用屏幕是登录屏幕,因此您只能在登录成功后将 Navigator.pop
发送到 Navigator.pushReplacementNamed
,将 login 替换为主页,并提供通过 /home
功能返回登录屏幕的方式。
我建议使用 Logout
来检查会话和重定向,而不是使用对 build
的检查,这样您就有了更简洁的重定向生命周期用法。我不明白的一件事是您没有在 initState
路线中定义。尽管它们看起来相同,但我已经看到了一些与此相关的问题,因为 /
定义了应用程序启动的视图,而 home
定义了路由映射,因此请尝试好吧,以防万一,删除其他变量,如果是这样的话(我个人只使用命名路由,以便在代码方面明确发送用户的位置)。
遵循一个使用 /
的示例,但使用 Option 1
中建议的使用 Option 2
:
initState
希望有帮助,如果没有,请让我知道您是否有任何疑问。