【问题标题】:How to prevent a Flutter app from routing to an incorrect page?如何防止 Flutter 应用路由到错误的页面?
【发布时间】:2023-04-01 14:50:02
【问题描述】:

我正在构建一个包含 基于角色的授权 的 Flutter 应用程序,但我很困惑为什么我的应用程序会将角色为 user 的人发送到仅适用于人的仪表板屏幕谁拥有teacher 角色。

注意:目前这是一个巨大的安全坑。用户甚至不应该知道这个仪表板的存在。我希望我的应用程序能够立即从 Cloud Firestore 获取用户文档并读取他们的角色。如果他们的角色是用户,请将他们发送到主屏幕。否则,角色必须是教师,所以将他们发送到教师仪表板。

我所看到的:我的应用程序将普通用户发送到仪表板约 2 秒,然后加载一点,然后将他们带到 HomeScreen。这意味着普通用户可以看到不应该发生的仪表板屏幕!

下面是我的代码:

bool isUser = false;

@override
Widget build(BuildContext context) {
    final authService = Provider.of < FirebaseAuthService > (context, listen: false);
    return StreamBuilder < User > (
        stream: authService.onAuthStateChanged,
        builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.active) {
                var user;
                if (snapshot.data != null) {
                    user = snapshot.data;
                    populateUserInfo(context, user.uid);
                }

                if (user == null) {
                    return LoginScreen();
                } else {
                    if (isUser) return HomeScreen();
                    else return DashboardScreen();
                }
            } else {
                return Scaffold(
                    body: Center(
                        child: CircularProgressIndicator()
                    )
                );
            }
        },
    );
}

Future < void > populateUserInfo(BuildContext context, String uid) async {
    final database = Provider.of < FirestoreService > (context, listen: false);
    isUser = await database.isUser(uid);
}

也许一种解决方法是在应用程序中设置手动延迟一段固定的时间,但该解决方案似乎非常手动且不安全。我不确定这是否是模拟器问题,因为它需要在我构建应用程序后同步文件。

有没有办法解决这个问题?

编辑(后续问题) - 有没有办法在 StreamBuilder 中运行异步任务而不返回空小部件?

【问题讨论】:

    标签: firebase flutter google-cloud-firestore firebase-authentication


    【解决方案1】:

    问题在于您的应用正在等待未来解决,一旦解决,它就会更正权限并且您的应用运行正常。发生这种情况是因为您的条件位于代码的同步部分。您可以通过执行以下操作将条件添加到异步部分来修复它:

    if (snapshot.data != null) {
        user = snapshot.data;
        populateUserInfo(context, user.uid).then((bool value) => {
            isUser = value;
            if (user == null) {
                return LoginScreen();
            } else {
                if (isUser) return HomeScreen();
                else return DashboardScreen();
            }
        });
    }else{
        // you logic in case the snapshot is null
    }
    

    另外,您必须将 populateUserInfo 函数更改为:

    Future < bool > populateUserInfo(BuildContext context, String uid) async {
        final database = Provider.of < FirestoreService > (context, listen: false);
        return await database.isUser(uid);
    }
    

    注意:这是未经测试的,但如果它不能立即工作,它应该是修复它的一个很好的起点。

    【讨论】:

    • 运行您的代码时,我收到一条错误消息,提示“构建函数不得返回 null”。你知道有没有办法在 StreamBuilder 中设置异步等待?
    • 更新 - 我设法摆脱了那个错误并实现了 Promise,但无论如何我总是被发送到 LoginScreen()。请看看我的飞镖:dartpad.dev/bd2d5f08cd45865d8383234d0739cb80
    • 不是有一个额外的return LoginScreen(); 导致了这种情况吗?根据我在 dartpad 上看到的最终返回,谁在你的条件之外并且它总是被执行,导致这个,删除它并让我知道这是否有效
    • 如果我删除它,我会得到一个异常。异常的要点是构建函数永远不能返回 null。这就是我将 LoginScreen() 添加到末尾的原因。
    • 在这个community post 中也有与您类似的问题,建议的解决方案是使用加载指示器,因为异步函数不会等待未来的完成。这也是我对你的情况的建议
    猜你喜欢
    • 1970-01-01
    • 2022-11-03
    • 2020-10-25
    • 1970-01-01
    • 2017-09-15
    • 2020-09-12
    • 2022-11-30
    • 2023-03-04
    • 1970-01-01
    相关资源
    最近更新 更多