Flutter 使用自定义fluro 路由实现访问权限控制

简介: 本篇介绍了利用 Fluro 路由管理实现路由权限拦截的两种方式,两种方式各有好处,使用过程中可以根据实际情况决定使用哪一种方法。
之前几篇介绍了 fluro 的路由管理和转场动画,本篇介绍如何完成路由拦截,进而实现权限管理。“此路是我开,此树是我栽。若是没权限,403到来!”

fluro 路由拦截思路

fluro 本身并没有提供类似 Flutter 自带的 onGenerateRoute方法来在每次跳转时进行路由拦截响应。我们可以通过两种方式实现路由拦截,一是在定义路由的时候,对于未授权的路由地址跳转到403未授权页面;二是继承 FluroRouter 类,重写其中的部分方法。通过阅读源码可以发现可以在子类覆盖 navigateTo 方法来进行路由拦截。

定义路由时拦截

这种方式比较简单,首先需要使用 Map定义一个路由表,将路由路径对应的路由处理器做一个映射,以便在定义路由的时候将路由路径与授权路由表进行比较,若在授权路由表内,则正常定义路由;否则使用403未授权页面替换。代码如下所示:

//完整路由表
static final routeTable = {
  loginPath: Handler(
      handlerFunc: (BuildContext context, Map<String, dynamic> params) {
    return LoginPage();
  }),
  dynamicDetailPath: Handler(
      handlerFunc: (BuildContext context, Map<String, dynamic> params) {
    return DynamicDetailPage(params['id'][0]);
  }),
  splashPath: Handler(
      handlerFunc: (BuildContext context, Map<String, dynamic> params) {
    return Splash();
  }),
  transitionPath: Handler(
      handlerFunc: (BuildContext context, Map<String, dynamic> params) {
    return TransitionPage();
  }),
  homePath: Handler(
      handlerFunc: (BuildContext context, Map<String, dynamic> params) {
    return AppHomePage();
  }),
};

//未授权页面处理器
static final permissionDeniedHandler =
    Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
  return PermissionDenied();
});

//定义路由
//添加路由时,将路由路径与白名单进行比对
//若不在白名单内,则使用未授权路由处理器
static void defineRoutes({List<String> whiteList}) {
  routeTable.forEach((path, handler) {
    if (whiteList == null || whiteList.contains(path)) {
      router.define(path, handler: handler);
    } else {
      router.define(path,
          handler: permissionDeniedHandler,
          transitionType: TransitionType.material);
    }
  });

  router.notFoundHandler = Handler(
      handlerFunc: (BuildContext context, Map<String, dynamic> params) {
    return NotFound();
  });
}

这种方式实现起来简单,但是为了保证路由拦截有效,必须在初始化路由前就通过登录人信息拿到路由白名单。为了改善用户体验,可以预先明确哪些页面不涉及权限管控(如闪屏页,首页,登录页),将这些页面直接添加。

跳转时拦截

跳转时拦截需要另外定义 FluroRouter 的子类,通过覆盖navigatoTo方法来实现路由拦截。这里有点特殊的是,由于路由跳转时的路径可能携带参数,不能像定义路由拦截那样直接和白名单进行比对。但是可以定义一个路由路径匹配方法来判断当前路由和白名单的是否匹配决定是否要做权限拦截。

fluro 既然能够按路径路由肯定提供了对应的路由路径匹配方法,扒一下源码,可以发现有一个match方法用于匹配路由路径。如果匹配成功,则返回匹配的路由对象AppRouteMatch,如果没有匹配到则返回 null

/// Finds a defined [AppRoute] for the path value.
/// If no [AppRoute] definition was found
/// then function will return null.
AppRouteMatch? match(String path) {
  return _routeTree.matchRoute(path);
}

AppRouteMatch类有一个AppRouteroute属性,route属性下还有一个 字符串类型的route属性,即匹配到的路由路径。

class AppRoute {
  String route;
  dynamic handler;
  TransitionType? transitionType;
  Duration? transitionDuration;
  RouteTransitionsBuilder? transitionBuilder;
  AppRoute(this.route, this.handler,
      {this.transitionType, this.transitionDuration, this.transitionBuilder});
}

因此可以通过该方式来检测是否和白名单的路由匹配,如果不匹配就调到403页面。我们定义了一个FluroRouter 的子类PermissionRouter,有两个属性,分别是 白名单列表_whiteList 和403页面路由地址 _permissionDeniedPath。在覆盖的 navigateTo方法中通过路由路径匹配方式来决定是否进行路由拦截。

import 'package:flutter/material.dart';
import 'package:fluro/fluro.dart';

class PermissionRouter extends FluroRouter {
  List<String> _whiteList;
  set whiteList(value) => _whiteList = value;

  String _permissionDeniedPath;
  set permissionDeniedPath(value) => _permissionDeniedPath = value;

  @override
  Future navigateTo(
    BuildContext context,
    String path, {
    bool replace = false,
    bool clearStack = false,
    bool maintainState = true,
    bool rootNavigator = false,
    TransitionType transition,
    Duration transitionDuration,
    transitionBuilder,
    RouteSettings routeSettings,
  }) {
    String pathToNavigate = path;
    AppRouteMatch routeMatched = this.match(path);
    String routePathMatched = routeMatched?.route?.route;
    if (routePathMatched != null) {
      //设置了白名单且当前路由不在白名单内,更改路由路径到授权被拒绝页面
      if (_whiteList != null && !_whiteList.contains(routePathMatched)) {
        pathToNavigate = _permissionDeniedPath;
      }
    }
    return super.navigateTo(context, pathToNavigate,
        replace: replace,
        clearStack: clearStack,
        maintainState: maintainState,
        rootNavigator: rootNavigator,
        transition: transition,
        transitionDuration: transitionDuration,
        transitionBuilder: transitionBuilder,
        routeSettings: routeSettings);
  }
}

这种方式需要首先定义好全部路由对应的路由处理器,然后在跳转时再拦截。因此假设首页是不涉及授权的,可以在 App 启动后再获取授权白名单,而不需要在启动时获取,可以降低启动时的任务,加快启动速度和提高用户体验。

总结

本篇介绍了利用 Fluro 路由管理实现路由权限拦截的两种方式,两种方式各有好处,使用过程中可以根据实际情况决定使用哪一种方法。


欢迎关注个人公众号:岛上码农

相关文章
|
23天前
|
前端开发 搜索推荐
Flutter中自定义气泡框效果的实现
Flutter中自定义气泡框效果的实现
30 3
|
2月前
|
前端开发
Flutter快速实现自定义折线图,支持数据改变过渡动画
Flutter快速实现自定义折线图,支持数据改变过渡动画
46 4
Flutter快速实现自定义折线图,支持数据改变过渡动画
|
2月前
|
开发者 监控 开发工具
如何将JSF应用送上云端?揭秘在Google Cloud Platform上部署JSF应用的神秘步骤
【8月更文挑战第31天】本文详细介绍如何在Google Cloud Platform (GCP) 上部署JavaServer Faces (JSF) 应用。首先,确保已准备好JSF应用并通过Maven构建WAR包。接着,使用Google Cloud SDK登录并配置GCP环境。然后,创建`app.yaml`文件以配置Google App Engine,并使用`gcloud app deploy`命令完成部署。最后,通过`gcloud app browse`访问应用,并利用GCP的监控和日志服务进行管理和故障排查。整个过程简单高效,帮助开发者轻松部署和管理JSF应用。
41 0
|
2月前
|
开发者 容器 Java
Azure云之旅:JSF应用的神秘部署指南,揭开云原生的新篇章!
【8月更文挑战第31天】本文探讨了如何在Azure上部署JavaServer Faces (JSF) 应用,充分发挥其界面构建能力和云平台优势,实现高效安全的Web应用。Azure提供的多种服务如App Service、Kubernetes Service (AKS) 和DevOps简化了部署流程,并支持应用全生命周期管理。文章详细介绍了使用Azure Spring Cloud和App Service部署JSF应用的具体步骤,帮助开发者更好地利用Azure的强大功能。无论是在微服务架构下还是传统环境中,Azure都能为JSF应用提供全面支持,助力开发者拓展技术视野与实践机会。
13 0
|
2月前
|
开发框架 API 开发者
Flutter表单控件深度解析:从基本构建到高级自定义,全方位打造既美观又实用的移动端数据输入体验,让应用交互更上一层楼
【8月更文挑战第31天】在构建美观且功能强大的移动应用时,表单是不可或缺的部分。Flutter 作为热门的跨平台开发框架,提供了丰富的表单控件和 API,使开发者能轻松创建高质量表单。本文通过问题解答形式,深入解读 Flutter 表单控件,并通过具体示例代码展示如何构建优秀的移动应用表单。涵盖创建基本表单、处理表单提交、自定义控件样式、焦点管理和异步验证等内容,适合各水平开发者学习和参考。
31 0
|
3月前
flutter 导航组件 AppBar (含顶部选项卡TabBar,抽屉菜单 drawer ,自定义导航图标)
flutter 导航组件 AppBar (含顶部选项卡TabBar,抽屉菜单 drawer ,自定义导航图标)
37 1
|
3月前
Flutter-自定义画板
Flutter-自定义画板
27 0
Flutter-自定义画板
|
3月前
|
移动开发 UED 容器
Flutter-自定义可展开文本控件
Flutter-自定义可展开文本控件
70 0
|
3月前
Flutter-自定义折叠流布局实现
Flutter-自定义折叠流布局实现
50 0
|
3月前
Flutter-自定义三角形评分控件
Flutter-自定义三角形评分控件
32 0

相关实验场景

更多
下一篇
无影云桌面