Как перенаправить на страницу входа, если ответ Flutter API неавторизован? - PullRequest
2 голосов
/ 05 августа 2020

Я создаю приложение Flutter, которое использует Golang API для получения данных. API вернет ошибку 401 unauthorized, если токен JWT недействителен. Как я могу перенаправить на страницу входа в систему при любом вызове API, если статус ответа 401?

Вот мой код флаттера:

main.dart

void main() async {

  WidgetsFlutterBinding.ensureInitialized();

  Provider.debugCheckInvalidValueType = null;

  AppLanguage appLanguage = AppLanguage();
  
  await appLanguage.fetchLocale();
  
  runApp(MyApp(
    appLanguage: appLanguage,
  ));

}

class MyApp extends StatelessWidget {
  
  final AppLanguage appLanguage;

  MyApp({this.appLanguage});

  @override
  Widget build(BuildContext context) {

    return  MultiProvider(
          
                  providers: providers,

                  child: MaterialApp(
                            
                      localizationsDelegates: [
                         AppLocalizations.delegate,
                         GlobalMaterialLocalizations.delegate,
                         GlobalWidgetsLocalizations.delegate,
                      ],
          
                  initialRoute: RoutePaths.Login,
                  onGenerateRoute: Router.generateRoute,
                  )        
               );
        }  
}

таблицы .dart

class Tables extends StatelessWidget {

  const Tables({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {

    return BaseWidget<TablesModel>(
    
        model: TablesModel(api: Provider.of(context, listen: false)),
    
        onModelReady: (model) => model.fetchTables(),
    
        builder: (context, model, child) => model.busy

            ? Center(

                child: CircularProgressIndicator(),
              
              )
        
            : Expanded(
               
                 child: GridView.builder (
---

table_model.dart

class TablesModel extends BaseModel {
  
  Api _api;

  TablesModel({@required Api api}) : _api = api;

  List<Tbl> tables;

  Future fetchTables() async {
    setBusy(true);
    tables = await _api.getTables();
    setBusy(false);
  }

  @override
  void dispose() {
    print('Tables has been disposed!!');
    super.dispose();
  }
}

api.dart

Future<List<Tbl>> getTables() async {
    
    var tables = List<Tbl>();

    try {

        var response = await http.get('$_baseUrl/tables/list');

        var parsed = json.decode(response.body) as List<dynamic>;
    
        if (parsed != null) {

           for (var table in parsed) {
    
               tables.add(Tbl.fromJson(table));
    
           }
        }

    } catch (e) {print(e); return null;}

    return tables;
  }

1 Ответ

2 голосов
/ 08 августа 2020

Поскольку у вас уже есть MaterialApp в вашем дереве и зарегистрированные именованные маршруты, это должно быть так же просто, как добавить вызов pu sh на вашу страницу входа примерно в то же время, когда вы получите ответ.

Во-первых, вы должны изменить getTables, чтобы проверить response на наличие кода состояния с помощью свойства statusCode объекта Response, отображаемого следующим блоком кода:

var response = await http.get('$_baseUrl/tables/list');

if(response.statusCode == 401) {
  //Act on status of 401 here
}

Теперь, когда у вас есть способ проверить, имеет ли ответ код состояния 401, вы можете перейти на свою страницу входа с помощью Navigator. Для Navigator требуется BuildContext, поэтому его нужно передать в функцию getTables.

Это включает в себя изменение getTables на:

Future<List<Tbl>> getTables(BuildContext context) async {

и fetchTables необходимо аналогичное изменение:

Future fetchTables(BuildContext context) async {

Затем, при вызове этих методов, вы передаете context вниз:

In Tables

model.fetchTables(context)

В TablesModel

Future fetchTables(BuildContext context) async {
  setBusy(true);
  tables = await _api.getTables(context);
  setBusy(false);
}

и, наконец, в getTables, вы используете переданный context, чтобы использовать Navigator:

Future<List<Tbl>> getTables(BuildContext context) async {
  var tables = List<Tbl>();
  try {
      var response = await http.get('$_baseUrl/tables/list');

      //Check response status code
      if(response.statusCode == 401) {
        Navigator.of(context).pushNamed(RoutePaths.Login);//Navigator is used here to go to login only with 401 status code
        return null;
      }

      var parsed = json.decode(response.body) as List<dynamic>;

      if (parsed != null) {
         for (var table in parsed) {
             tables.add(Tbl.fromJson(table));
         }
      }

  } catch (e) {print(e); return null;}
  return tables;
}

Вместо Navigator.of(context).pushNamed(RoutePaths.Login); вы можете использовать Navigator.pushNamed(context, RoutePaths.Login);, если хотите, но, как вы можете прочитать на этот ответ , они внутренне делают то же самое.

Теперь, когда есть код состояния 401, пользователь будет перемещен на экран входа в систему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...