Как перенаправить пользователя на страницу входа, если срок действия токена истек

привет, у меня есть случай, когда по истечении срока действия токена пользователя пользователь не переключается на страницу loginPage, хотя я установил его здесь. как решить эту проблему спасибо.

я установил его на заставке, если токен не равен нулю, затем перейдите на главную страницу, а если токен равен нулю, перейдите на страницу входа. но когда срок действия токена истекает, он все еще остается на главной странице

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

и функция при входе пользователя

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;
                                        Navigator.pushNamedAndRemoveUntil(
                                          context,
                                          '/main',
                                          (route) => false,
                                        );
                                      }
                                    }
                                  },
                                ),

и этот вызов апи

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'];
        //Ini mulai nyimpen token
        await UtilSharedPreferences.setToken(token);
        print(token);
        // print(await UtilSharedPreferences.getToken());
        return User.fromJson(jsonDecode(response.body));
      } else {
        return null;
      }
    } catch (e) {
      print(e);
      throw Exception();
    }
  }

В этом случае вам также необходимо сохранить дату истечения срока действия токена в общих настройках и проверить на заставке, является ли эта дата в прошлом или нет, и если эта дата в прошлом, вы перенаправляетесь на вход в систему или на главный экран. Основная причина этого заключается в том, что даже если срок действия вашего токена истек, он не будет удален из общего предпочтения сам по себе, и вам необходимо удалить его вручную, если вы получите 401 или несанкционированный ответ от любого API.

Karan Mehta 28.12.2022 07:24

я думаю, вам нужно создать один базовый класс API, где вы можете обрабатывать все ответы API от одного класса и устанавливать условие для кода состояния, если вы получаете код состояния 401 (истечение срока действия токена), затем перейдите к экрану входа в систему. это упростит вашу работу с каждого экрана или API, вам не нужно каждый раз делать такой код.

Sumita Naiya 28.12.2022 07:28

Я обновил, как мне решить эту проблему?

sharon 28.12.2022 07:36
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
163
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если ваша функция истечения сеанса имеет некоторый предопределенный интервал или логику, вам необходимо реализовать ее на экране-заставке, и на ее основе вы можете перемещаться по пользователю дальше. В противном случае вы хотите обработать его в ответе API, только если у вас есть условие добавления для statusCode 401.

checkSessionExpire(BuildContext context)
   if (response.statusCode == 200) { 
      //SuccessWork
   } else if (response.statusCode == 401) {
      //SessionExpire
   } else {
      return null
   }
}
pastebin.com/NrTy2y30 Неопределенное имя «контекст». Попробуйте исправить имя на определенное или определить имя.
sharon 28.12.2022 08:57

Вы должны передать BuildContext в качестве параметра функции, чтобы использовать его, я обновил код. Пожалуйста, проверьте.

Khyati Modi 29.12.2022 07:26
pastebin.com/cLUn83ac все еще получаю ошибку, как ее исправить или, может быть, я неправильно выразился
sharon 29.12.2022 08:03

В вашей функции входа в систему вы должны передать buildContext. В моем коде checkSessionExpire — это имя функции. Удалите его из своего кода и добавьте контекст в функцию входа в систему. т. е. Future<User?> логин (String nim, String password, контекст BuildContext)

Khyati Modi 29.12.2022 08:20

Хорошо, передайте контекст туда. ожидание userProvider.login(nimController.text, passwordController.text, контекст)

Khyati Modi 29.12.2022 08:31

результат все тот же, когда срок действия моего токена истекает, он не переходит на страницу loginPage

sharon 29.12.2022 08:39

Отследите ответ, вы получаете код ответа 401? Если да, добавьте какой-нибудь журнал, если условие, чтобы проверить, удовлетворяет ли эта строка кода условию или нет. Затем добавьте свой код маршрутизации в условие if else - else if (response.statusCode == 401) { // здесь добавьте журнал }

Khyati Modi 29.12.2022 08:42

как, я немного запутался здесь

sharon 29.12.2022 09:12

с помощью оператора печати или точек останова вы можете легко отлаживать статус ответа и строки кода,

Khyati Modi 29.12.2022 09:52

Я пробовал, результат 401, не авторизован, и страницы не перемещаются.

sharon 29.12.2022 10:06
stackoverflow.com/questions/63271031/…
Khyati Modi 29.12.2022 10:10
Ответ принят как подходящий

вы можете просто создать свой собственный HTTP-клиент с помощью Dio и добавить Interceptor для автоматической регенерации idToken, если срок его действия истек, с использованием данного refreshToken.

Клиент Http выдает ошибку, если срок действия refreshToken также истекает.

В этом случае просто перейдите к экрану входа.

Полный код для добавления перехватчика и создания собственного HTTP-клиента приведен ниже.

import 'package:dio/dio.dart';

import '../utils/shared_preference.dart';

class Api {
  static Dio? _client;
  static Dio clientInstance() {
    if (_client == null) {
      _client = Dio();
      _client!.interceptors
          .add(InterceptorsWrapper(onRequest: (options, handler) async {
        if (!options.path.contains('http')) {
          options.path = 'your-server' + options.path;
        }
        options.headers['Authorization'] =
            'Bearer ${PreferenceUtils.getString('IdToken')}';
        return handler.next(options);
      }, onError: (DioError error, handler) async {
        if ((error.response?.statusCode == 401 &&
            error.response?.data['message'] == "Invalid JWT")) {
          if (PreferenceUtils.exists('refreshToken')) {
            await _refreshToken();
            return handler.resolve(await _retry(error.requestOptions));
          }
        }
        return handler.next(error);
      }));
    }
    return _client!;
  }

  static Future<void> _refreshToken() async {
    final refreshToken = PreferenceUtils.getString('refreshToken');
    final response = await _client!
        .post('/auth/refresh', data: {'refreshToken': refreshToken});

    if (response.statusCode == 201) {
      // successfully got the new access token
      PreferenceUtils.setString('accessToken', response.data);
    } else {
      // refresh token is wrong so log out user.
      PreferenceUtils.deleteAll();
    }
  }

  static Future<Response<dynamic>> _retry(RequestOptions requestOptions) async {
    final options = Options(
      method: requestOptions.method,
      headers: requestOptions.headers,
    );
    return _client!.request<dynamic>(requestOptions.path,
        data: requestOptions.data,
        queryParameters: requestOptions.queryParameters,
        options: options);
  }
}

Dio client = Api.clientInstance();
var resposne = (hit any request);
   if (error in response is 401){
  //it is sure that 401 is because of expired refresh token as we 
  //already handled idTokoen expiry case in 401 error while 
  //adding interceptor.
navigate to login screen for logging in again.
}

Пожалуйста, примите решение, если оно решает вашу проблему.

Другие вопросы по теме