防止未经身份验证的用户在 flutter web 应用程序中使用 URL 导航到路由?

Cha*_*acl 7 routes flutter flutter-web

我正在尝试在 Flutter 中创建一个网络应用程序,理想情况下它可以像网站一样工作。用户将登录并能够查看包含私人信息的仪表板,但某些屏幕上包含公共信息,任何人都可以使用动态路由 URL 导航到这些信息,例如: ,myflutterapp.com/feed/usersPublicInfo该链接可以发布到另一个网站,例如用户可以直接进入该路线。

显然,使用命名路由是我需要的解决方案,但是是什么阻止某人直接访问包含私人信息的路由呢?或者至少防止用户进入包含null信息的页面并导致小部件崩溃?

解决思路1

使用命名路由,并在登录屏幕之后将用户变量传递到每个屏幕,并在生成路由之前进行空检查。如果为空,则意味着有人跳过了一些路线,并且他们被发送回登录

解决思路2

如果可能,请混合使用命名路由和“未命名”路由,例如提要、仪表板和登录屏幕。用户进入仪表板后,所有路由都将使用 Navigator.push() 进行处理,从而防止从 URL 访问它们

其他解决方案?

我对 flutter 和 flutter web 相当陌生,所以我可能会完全错误地解决这个问题。我希望得到一些建议。谢谢!

小鹿-*_*小鹿- 6

static Future<void> init() async {
    WidgetsFlutterBinding.ensureInitialized();
    if(kIsWeb) {
      final String defaultRouteName = WidgetsBinding.instance.window.defaultRouteName;
      if(!(defaultRouteName == 'home' || defaultRouteName == 'login' || defaultRouteName == '/')) {
        SystemNavigator.routeUpdated(
           routeName: '/',
           previousRouteName: null
        );
      }
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 如果你愿意尝试一下google翻译:你需要先简单了解三点1,WidgetsBinding.instance.window.defaultRouteName是引擎获取到的平台的默认路由名称(在web平台就是url中hash部分)2,在web中查看浏览器或者点击链接打开新页面都会重新构建整个应用的,这也是你出错的原因,整个应用都被刷新了,路由参数当然也没有了。 3、你可以在WidgetApp类的源码中看到创建Navigator的实现:如果存在WidgetsBinding.instance.window.defaultRouteName就用它作为默认路由名称并且会覆盖你自己配置的默认路由名称知道这些之后,那我们只要在WidgetApp构建之前修改window.defaultRouteName就行。用WidgetsBinding。 instance.window.defaultRouteName和你自己的路由表进行对比(根据你的需要进行检查)。如果满足条件就放行,如果不满足就调用SystemNavigator.routeUpdated进行修改...抱歉我不会英语,不能求助太多了。如果有哪里我没说清楚的地方可以继续问我。 (2认同)

Ald*_*uan 3

解决方案 1 对我来说看起来不错。

对于我的建议,使用Provider进行状态管理。这是我基于上下文的示例:

    routes: {
      "/": (context) => MainPage(),
      "/detail": (context) => UserDetailPage(),
      "/other": (context) => OtherPage(),
    },
 builder: (context, child) {
          return Consumer<UsersProvider>(
            child: child,
            builder: (context, provider, child) {
              if (provider.isLoading) {
                return Scaffold(
                  body: Center(
                    child: CircularProgressIndicator(),
                  ),
                );
              }

              final value = provider.user;
              if (value == null) {
                return Navigator(
                  onGenerateRoute: (settings) => MaterialPageRoute(
                      settings: settings, builder: (context) => LoginPage()),
                );
              }

              return MultiProvider(
                providers: [
                  ChangeNotifierProvider(create: (context) => UsersProvider()),
                  ChangeNotifierProvider(
                      create: (context) => InvoicesProvider()),
                  ChangeNotifierProvider(create: (context) => EventsProvider()),
                ],
                child: child,
              );
            },
          );
Run Code Online (Sandbox Code Playgroud)

基本上使用构建器并main.dart定义路由,然后在构建器内部使用 Consumer were child 是初始路由MainPage(),因此如果用户已经登录,他们将转到那里,如果没有,则基于我上下文中的标志,isAdmin他们将重定向到 LoginPage() 。因此,如果他们尝试使用 url 访问详细信息或其他内容,他们LoginPage无论如何都会重定向到。

这是我的用户提供者:

  getUser() async {
    FirebaseAuth.instance.onAuthStateChanged.listen((currentUser) async {
      _isLoading = false;
      if (currentUser == null) {
        _user = null;
        notifyListeners();
        return;
      }
      final data = await Firestore.instance
          .document("users/${currentUser.uid}")
          .snapshots()
          .first;
      if (data.exists) {
        print(data.data);
        if (data.data['is_admin'] == true) {
          _user = User.fromMap(data.data);
          notifyListeners();
        }
        return null;
      }
    });
  }
Run Code Online (Sandbox Code Playgroud)

所以如果用户isAdmin它会返回他们的值。我希望你能理解我的解释。我希望这对您也有帮助。