Flutter如何完成路由攔截,實(shí)現(xiàn)權(quán)限管理
之前幾篇介紹了 fluro 的路由管理和轉(zhuǎn)場(chǎng)動(dòng)畫(huà),本篇介紹如何完成路由攔截,進(jìn)而實(shí)現(xiàn)權(quán)限管理?!按寺肥俏议_(kāi),此樹(shù)是我栽。若是沒(méi)權(quán)限,403到來(lái)!”
相關(guān)文章
若想了解 flutter 的路由相關(guān)篇章,請(qǐng)查閱下面的篇章:
//www.dbjr.com.cn/article/215167.htm
//www.dbjr.com.cn/article/214856.htm
//www.dbjr.com.cn/article/215564.htm
//www.dbjr.com.cn/article/215549.htm
//www.dbjr.com.cn/article/215569.htm
fluro 路由攔截思路
fluro 本身并沒(méi)有提供類(lèi)似 Flutter 自帶的 onGenerateRoute方法來(lái)在每次跳轉(zhuǎn)時(shí)進(jìn)行路由攔截響應(yīng)。我們可以通過(guò)兩種方式實(shí)現(xiàn)路由攔截,一是在定義路由的時(shí)候,對(duì)于未授權(quán)的路由地址跳轉(zhuǎn)到403未授權(quán)頁(yè)面;二是繼承 FluroRouter 類(lèi),重寫(xiě)其中的部分方法。通過(guò)閱讀源碼可以發(fā)現(xiàn)可以在子類(lèi)覆蓋 navigateTo 方法來(lái)進(jìn)行路由攔截。
定義路由時(shí)攔截
這種方式比較簡(jiǎn)單,首先需要使用 Map定義一個(gè)路由表,將路由路徑對(duì)應(yīng)的路由處理器做一個(gè)映射,以便在定義路由的時(shí)候?qū)⒙酚陕窂脚c授權(quán)路由表進(jìn)行比較,若在授權(quán)路由表內(nèi),則正常定義路由;否則使用403未授權(quán)頁(yè)面替換。代碼如下所示:
//完整路由表 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(); }), }; //未授權(quán)頁(yè)面處理器 static final permissionDeniedHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) { return PermissionDenied(); }); //定義路由 //添加路由時(shí),將路由路徑與白名單進(jìn)行比對(duì) //若不在白名單內(nèi),則使用未授權(quán)路由處理器 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(); }); }
這種方式實(shí)現(xiàn)起來(lái)簡(jiǎn)單,但是為了保證路由攔截有效,必須在初始化路由前就通過(guò)登錄人信息拿到路由白名單。為了改善用戶體驗(yàn),可以預(yù)先明確哪些頁(yè)面不涉及權(quán)限管控(如閃屏頁(yè),首頁(yè),登錄頁(yè)),將這些頁(yè)面直接添加。
跳轉(zhuǎn)時(shí)攔截
跳轉(zhuǎn)時(shí)攔截需要另外定義 FluroRouter 的子類(lèi),通過(guò)覆蓋navigatoTo方法來(lái)實(shí)現(xiàn)路由攔截。這里有點(diǎn)特殊的是,由于路由跳轉(zhuǎn)時(shí)的路徑可能攜帶參數(shù),不能像定義路由攔截那樣直接和白名單進(jìn)行比對(duì)。但是可以定義一個(gè)路由路徑匹配方法來(lái)判斷當(dāng)前路由和白名單的是否匹配決定是否要做權(quán)限攔截。
fluro 既然能夠按路徑路由肯定提供了對(duì)應(yīng)的路由路徑匹配方法,扒一下源碼,可以發(fā)現(xiàn)有一個(gè)match方法用于匹配路由路徑。如果匹配成功,則返回匹配的路由對(duì)象AppRouteMatch,如果沒(méi)有匹配到則返回 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類(lèi)有一個(gè)AppRoute類(lèi) route屬性,route屬性下還有一個(gè) 字符串類(lèi)型的route屬性,即匹配到的路由路徑。
class AppRoute { String route; dynamic handler; TransitionType? transitionType; Duration? transitionDuration; RouteTransitionsBuilder? transitionBuilder; AppRoute(this.route, this.handler, {this.transitionType, this.transitionDuration, this.transitionBuilder}); }
因此可以通過(guò)該方式來(lái)檢測(cè)是否和白名單的路由匹配,如果不匹配就調(diào)到403頁(yè)面。我們定義了一個(gè)FluroRouter 的子類(lèi)PermissionRouter,有兩個(gè)屬性,分別是 白名單列表_whiteList 和403頁(yè)面路由地址 _permissionDeniedPath。在覆蓋的 navigateTo方法中通過(guò)路由路徑匹配方式來(lái)決定是否進(jìn)行路由攔截。
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) { //設(shè)置了白名單且當(dāng)前路由不在白名單內(nèi),更改路由路徑到授權(quán)被拒絕頁(yè)面 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); } }
這種方式需要首先定義好全部路由對(duì)應(yīng)的路由處理器,然后在跳轉(zhuǎn)時(shí)再攔截。因此假設(shè)首頁(yè)是不涉及授權(quán)的,可以在 App 啟動(dòng)后再獲取授權(quán)白名單,而不需要在啟動(dòng)時(shí)獲取,可以降低啟動(dòng)時(shí)的任務(wù),加快啟動(dòng)速度和提高用戶體驗(yàn)。
以上就是Flutter如何完成路由攔截,實(shí)現(xiàn)權(quán)限管理的詳細(xì)內(nèi)容,更多關(guān)于Flutter 路由攔截的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
一文帶你了解Android系統(tǒng)的啟動(dòng)流程
Android系統(tǒng)的啟動(dòng)是一個(gè)復(fù)雜的過(guò)程,涉及到多個(gè)階段和組件,所以本文將給大家詳細(xì)的介紹一下Android系統(tǒng)的啟動(dòng)流程,文中也有圖片和代碼示例的講解,需要的朋友可以參考下2023-09-09Android嵌套滾動(dòng)和協(xié)調(diào)滾動(dòng)的多種實(shí)現(xiàn)方法
嵌套的滾動(dòng)主要方式就是這些,這些簡(jiǎn)單的效果我們用協(xié)調(diào)滾動(dòng),如?CoordinatorLayout?也能實(shí)現(xiàn)同樣的效果,這篇文章主要介紹了Android嵌套滾動(dòng)和協(xié)調(diào)滾動(dòng)的多種實(shí)現(xiàn)方法,需要的朋友可以參考下2022-06-06Android如何監(jiān)測(cè)文件夾內(nèi)容變化詳解
最近在開(kāi)發(fā)android應(yīng)用程序的時(shí)候遇到了一個(gè)監(jiān)測(cè)文件夾的功能,所以下面這篇文章主要給大家介紹了關(guān)于Android如何監(jiān)測(cè)文件夾內(nèi)容變化的相關(guān)資料,需要的朋友可以參考下2021-12-12安卓(Android)動(dòng)態(tài)創(chuàng)建多個(gè)按鈕并添加監(jiān)聽(tīng)事件
本文主要介紹Android動(dòng)態(tài)創(chuàng)建多個(gè)按鈕并給每個(gè)按鍵添加監(jiān)聽(tīng)事件,在做Android項(xiàng)目會(huì)經(jīng)常遇到的,希望對(duì)需要用到的同學(xué)有所幫助2016-07-07Android入門(mén)之使用RecyclerView完美實(shí)現(xiàn)瀑布流界面詳解
網(wǎng)上充滿著不完善的基于RecyclerView的瀑布流實(shí)現(xiàn),要么根本是錯(cuò)的、要么就是只知其一不知其二。本文就來(lái)用RecyclerView完美實(shí)現(xiàn)瀑布流界面,希望大家有所幫助2023-02-02Android自定義TextView實(shí)現(xiàn)文字傾斜效果
有時(shí)候Android自帶的控件無(wú)法滿足我們的某些要求,這時(shí)就需要我們自定義控件來(lái)實(shí)現(xiàn)這些功能。比如在實(shí)際開(kāi)發(fā)應(yīng)用中,我們有時(shí)需要將TextView的文字傾斜一定的角度,就需要自定義TextView。下面這篇文章就給大家介紹了利用Android TextView如何實(shí)現(xiàn)文字傾斜效果。2016-11-11Android自定義View實(shí)現(xiàn)五子棋游戲
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11Android 中ListView setOnItemClickListener點(diǎn)擊無(wú)效原因分析
這篇文章主要介紹了Android 中ListView setOnItemClickListener點(diǎn)擊無(wú)效原因分析的相關(guān)資料,需要的朋友可以參考下2016-01-01Ubuntu Android源碼以及內(nèi)核下載與編譯
本文主要介紹Android源碼的下載和編譯,這里整理了相關(guān)資料及如何下載和編譯的詳細(xì)步驟,有需要的小伙伴可以參考下2016-09-09