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 路由管理实现路由权限拦截的两种方式,两种方式各有好处,使用过程中可以根据实际情况决定使用哪一种方法。


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

相关文章
|
3天前
|
安全 Go 数据安全/隐私保护
Flutter开发笔记:Flutter路由技术
Flutter开发笔记:Flutter路由技术
383 0
|
3天前
|
前端开发 搜索推荐 开发者
【Flutter前端技术开发专栏】Flutter中的自定义主题与暗黑模式
【4月更文挑战第30天】本文介绍了如何在Flutter中自定义主题和实现暗黑模式。通过`ThemeData`类定义应用的外观,包括颜色、字体和样式。示例展示了如何设置主色、强调色及文本、按钮主题。暗黑模式可通过`darkTheme`属性启用,结合`ThemeData.dark()`方法定制。利用`MediaQuery`监听系统亮度变化,动态调整暗黑模式状态。Flutter的这些特性有助于开发者创建独特且用户友好的界面。
【Flutter前端技术开发专栏】Flutter中的自定义主题与暗黑模式
|
3天前
|
缓存 前端开发 搜索推荐
【Flutter前端技术开发专栏】Flutter中的自定义绘制与Canvas API
【4月更文挑战第30天】Flutter允许开发者通过`CustomPaint`和`CustomPainter`进行自定义绘制,以实现丰富视觉效果。`CustomPaint` widget将`CustomPainter`应用到画布,而`CustomPainter`需实现`paint`和`shouldRepaint`方法。`paint`用于绘制图形,如示例中创建的`MyCirclePainter`绘制蓝色圆圈。Canvas API提供绘制形状、路径、文本和图片等功能。注意性能优化,避免不必要的重绘和利用缓存提升效率。自定义绘制让Flutter UI更具灵活性和个性化,但也需要图形学知识和性能意识。
【Flutter前端技术开发专栏】Flutter中的自定义绘制与Canvas API
|
3天前
|
开发框架 前端开发 搜索推荐
【Flutter前端技术开发专栏】Flutter中的自定义Widget与渲染流程
【4月更文挑战第30天】探索Flutter的自定义Widget与渲染流程。自定义Widget是实现复杂UI设计的关键,优点在于个性化设计、功能扩展和代码复用,但也面临性能优化和复杂性管理的挑战。创建步骤包括设计结构、定义Widget类、实现构建逻辑和处理交互。Flutter渲染流程涉及渲染对象树、布局、绘制和合成阶段。实践案例展示如何创建带渐变背景和阴影的自定义按钮。了解这些知识能提升应用体验并应对开发挑战。查阅官方文档以深入学习。
【Flutter前端技术开发专栏】Flutter中的自定义Widget与渲染流程
|
3天前
|
前端开发 开发者 UED
Flutter的自定义Painter:深入探索自定义绘制Widget的技术实现
【4月更文挑战第26天】Flutter的自定义Painter允许开发者根据需求绘制独特UI,通过继承`CustomPaint`类和重写`paint`方法实现。在`paint`中使用`Canvas`绘制图形、路径等。创建自定义Painter类后,将其作为`CustomPaint` Widget的`painter`属性使用。此技术可实现自定义形状、渐变、动画等复杂效果,提升应用视觉体验。随着Flutter的进化,自定义Painter将提供更丰富的功能。
|
3天前
|
运维 监控 定位技术
应用研发平台EMAS常见问题之flutter插件不支持自定义图标如何解决
应用研发平台EMAS(Enterprise Mobile Application Service)是阿里云提供的一个全栈移动应用开发平台,集成了应用开发、测试、部署、监控和运营服务;本合集旨在总结EMAS产品在应用开发和运维过程中的常见问题及解决方案,助力开发者和企业高效解决技术难题,加速移动应用的上线和稳定运行。
81 0
|
3天前
|
BI
Flutter笔记:路由观察者
Flutter笔记:路由观察者
92 0
|
3天前
Flutter 自定义ICON库
Flutter 自定义ICON库 Flutter提供了一些内置的ICON库,但在实际开发中,可能需要一些自定义的ICON图标。Flutter允许我们使用自定义图标,本文将介绍如何创建和使用自定义ICON库。
|
3天前
|
UED
Flutter之自定义路由切换动画
Flutter之自定义路由切换动画 在Flutter中,我们可以通过Navigator来实现路由管理,包括路由的跳转和返回等。默认情况下,Flutter提供了一些简单的路由切换动画,但是有时候我们需要自定义一些特殊的动画效果来提高用户体验。本文将介绍如何在Flutter中实现自定义的路由切换动画。
|
3天前
|
开发框架 Dart 容器
Flutter 自定义渐变按钮 GradientButton
Flutter 自定义渐变按钮 GradientButton Flutter 是一种流行的跨平台移动应用开发框架。Flutter 提供了许多内置的小部件,但有时您可能需要创建自己的小部件以满足特定的需求。这个文档将介绍如何创建一个自定义渐变按钮小部件 GradientButton。