我正试图在Flutter中创建一个理想的网站应用程序。用户登录后可以看到带有私人信息的仪表板,但在某些带有公共信息的屏幕上,任何人都可以使用动态路线URL(如:myflutterapp.com/feed/usersPublicInfo
(导航到,例如,该链接可以发布到另一个网站,用户可以直接进入该路线。
很明显,使用命名路由是我需要的解决方案,但是什么阻止了某人直接进入私人信息所在的路由?或者至少防止用户转到包含null
信息的页面并导致小部件崩溃?
解决方案理念1
使用命名的Routes,在登录屏幕后,将用户变量传递到每个屏幕,并在生成路由之前进行nullcheck。如果它为空,则意味着有人跳过了一些路线,并将其发送回登录
解决方案理念2
如果可能的话,使用命名路线和";未命名的";路由,例如提要、仪表板和登录屏幕。一旦用户到达仪表板,所有路线都将使用Navigator.push((进行处理,从而防止从URL 访问它们
其他解决方案
我对扑腾和扑腾网络还很陌生,所以我可能会完全错了。如果能给我一些建议,我将不胜感激。谢谢
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
);
}
}
...
}
解决方案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,
);
},
);
基本上在main.dart
中使用构建器并定义路由,然后在构建器中使用Consumer are child是初始路由MainPage()
,所以如果用户已经登录,他们会去那里,如果没有,基于我上下文中的标志isAdmin
,他们会重定向到LoginPage((。所以,如果他们试图通过使用url来了解细节或其他内容,他们无论如何都会重定向到LoginPage
。
这是我的UserProvider:
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;
}
});
}
因此,如果用户isAdmin
将返回其值。我希望你能理解我的解释。我希望这对你也有帮助。