如何重定向如果令牌过期在Flutter与http

wkyowqbh  于 2023-04-07  发布在  Flutter
关注(0)|答案(2)|浏览(143)

我遇到了一个问题,当用户的令牌过期时,它应该返回到登录页面,但我遇到的情况是它没有返回到登录页面,而是在小部件中以文本“令牌过期”的形式给出了一个异常。
我的代码有问题吗?

这是登录页面小部件中的代码

Container(
                      width: double.infinity,
                      height: 45,
                      child: isLoading
                          ? Center(
                              child: CircularProgressIndicator(
                                color: primaryColor,
                              ),
                            )
                          : CustomButtonFilled(
                              title: 'Login',
                              onPressed: () async {
                                final prefs =
                                    await SharedPreferences.getInstance();
                                prefs.setString(Constant.token, '');
                                if (nimController.text.isEmpty ||
                                    passwordController.text.isEmpty) {
                                  showError('NIM/Password harus diisi');
                                } else {
                                  setState(() {
                                    isLoading = true;
                                  });
                                  User? user = await userProvider.login(
                                    nimController.text,
                                    passwordController.text,
                                  );
                                  setState(() {
                                    isLoading = false;
                                  });
                                  if (user == null) {
                                    showError('NIM/Password tidak sesuai!');
                                  } else {
                                    userProvider.user = user;
                                    // ignore: use_build_context_synchronously
                                    Navigator.pushNamedAndRemoveUntil(
                                      context,
                                      '/main',
                                      (route) => false,
                                    );
                                  }
                                }
                              },
                            ),
                    ),

调用API登录

Future<User?> login(String nim, String password) async {
    String url = Constant.baseURL;        try {
      var body = {
        'username': nim,
        'password': password,
      };
      var response = await http.post(
        Uri.parse(
          '$url/login_mhs',
        ),
        body: body,
      );
      if (response.statusCode == 200) {
        final token = jsonDecode(response.body)['data']['access_token'];
        await UtilSharedPreferences.setToken(token);
        print(token);
        return User.fromJson(jsonDecode(response.body));
      } else {
        return null;
      }
    } catch (e) {
      print(e);
      throw Exception();
    }
  }

窗口小部件闪屏

Future<void> toLogin() async {
    Timer(
      const Duration(seconds: 3),
      () async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        String? token = prefs.getString(Constant.token);
        // ignore: use_build_context_synchronously
        Navigator.pushReplacementNamed(
          context,
          token != null ? AppRoute.mainRoute : AppRoute.loginRoute,
          arguments: token,
        );
      },
    );
  }

  @override
  void initState() {
    super.initState();
    toLogin();
  }
wsxa1bj1

wsxa1bj11#

要解决此问题,您可以修改toLogin()函数以检查令牌是否为empty,并在这种情况下导航到登录页面:

Future<void> toLogin() async {
  WidgetsBinding.instance?.addPostFrameCallback(
    (_) {
      SharedPreferences prefs = await SharedPreferences.getInstance();
      String? token = prefs.getString(Constant.token);

      if (token == null || token.isEmpty) {
        Navigator.pushReplacementNamed(context, AppRoute.loginRoute);
      } else {
        Navigator.pushReplacementNamed(context, AppRoute.mainRoute);
      } 
    },
  );
}
oaxa6hgo

oaxa6hgo2#

您将令牌保存为共享首选项中的字符串。该字符串将始终存在并且永远不会过期。因此当您这样做时

Navigator.pushReplacementNamed(
          context,
          token != null ? AppRoute.mainRoute : AppRoute.loginRoute,
          arguments: token,
        );

它永远不会进入登录页面,因为令牌永远不会为null或空。当你向API发送请求时,它会告诉你令牌过期的结果,所以你想在从post请求中获得结果后处理页面更改。所以你的代码应该更像这样:

if (response.statusCode == 200) {
    return UserBiodata.fromJson(jsonDecode(response.body));
  } else {
    throw Exception('Token Expired');
    Navigator.pushReplacementNamed( context, AppRoute.loginRoute,);
  }

相关问题