如果Flutter API响应未经授权,如何重定向到登录页面?

时间:2020-08-05 18:03:27

标签: flutter go dart jwt

我正在构建一个Flutter应用程序,该应用程序使用Golang API来获取数据。如果JWT令牌无效,则API将返回未经授权的401。如果响应状态为401,如何在任何API调用上重定向到登录页面?

这是我的颤动代码:

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,
                  )        
               );
        }  
}

tables.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 (
---

tables_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 个答案:

答案 0 :(得分:2)

由于树中已经有MaterialApp并已注册了命名路由,因此这就像添加一个调用以在获得响应的同时推送登录页面一样简单。

首先,您应该修改getTables来检查response的状态代码,该状态代码具有Response对象的statusCode属性,并显示以下代码块:

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向下传递:

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);,但是正如您可以在this answer上阅读的那样,它们在内部执行相同的操作。

现在,当状态码为401时,用户将被导航到登录屏幕。

相关问题