關(guān)于門戶的前端權(quán)限管理
關(guān)注并將「趣談前端」設(shè)為星標(biāo)
每天早 08 : 30 按時(shí)推送技術(shù)干貨/優(yōu)秀開源/技術(shù)思維
?前沿:我所理解的門戶Portal就是一個(gè)入口, 可快速整合應(yīng)用入口,用來統(tǒng)一賬號管理、統(tǒng)一認(rèn)證登錄,打破信息孤島等,做統(tǒng)一的權(quán)限管理,也可以實(shí)現(xiàn)單點(diǎn)登錄 SSO。早期的MVC時(shí)代,web應(yīng)用其實(shí)就有通過權(quán)限去控制頁面、菜單、按鈕等的顯示和隱藏,只不過呈現(xiàn)方式不同,大多以php和jsp等為主,隨著前后端分離后,前端也成了權(quán)限控制的扛把子,主要是從以下這幾個(gè)角度去實(shí)現(xiàn),路由層面、視圖層面以及接口層面
?

1.路由層面
?一般SPA應(yīng)用結(jié)合vue-router和vuex實(shí)現(xiàn)完成的一套路由體系,主要兩種方式,一種是通過vue-router addRoutes 方法注入路由實(shí)現(xiàn)控制,另外一個(gè)是直接通過vue-router beforeEach鉤子限制路由跳轉(zhuǎn)
?
1.1 router.beforeEach()
?beforeEach鉤子函數(shù)就是在路由跳轉(zhuǎn)前執(zhí)行的,通過注冊 router.beforeEach 鉤子對路由的每次跳轉(zhuǎn)進(jìn)行管理,每次跳轉(zhuǎn)都進(jìn)行檢查,如果目標(biāo)路由不存再于基本路由和當(dāng)前用戶的用戶路由中,則取消跳轉(zhuǎn),轉(zhuǎn)為跳轉(zhuǎn)錯(cuò)誤頁或登錄頁面
?
在路由定義時(shí)添加meta的一個(gè)屬性,來控制判斷該頁面是否需要登錄權(quán)限

1.2 動態(tài)路由 (DynamicRoutes)
?用來實(shí)現(xiàn)頁面訪問權(quán)限,動態(tài)路由通過
?router.addRoutes(),來只掛載當(dāng)前用戶擁有權(quán)限的路由,如果用戶直接訪問未授權(quán)的路由,則會進(jìn)入404頁面。但是前提是需要用戶登錄后獲取路由權(quán)限,一般動態(tài)掛載是在router.beforeEach處理的,下面我們看具體實(shí)現(xiàn)
定義好需要動態(tài)掛載的路由,區(qū)分是分為初始路由和根據(jù)role角色來動態(tài)掛載的“用戶路由”,比如
constantRoutes和asyncRoutesrouter.beforeEach添加router.addRoutes事件 文檔鏈接??
為了防止重復(fù)配置相同路由,在添加路由之前判斷是否已經(jīng)存在角色權(quán)限
獲取擁有權(quán)限的路由, generateRoutes的實(shí)現(xiàn)

通過遞歸的方式去過濾去用戶的路由權(quán)限,通過router.addRoutes()動態(tài)添加所有符合權(quán)限的路由,當(dāng)然這種方式需要依賴后端。對于不同角色的用戶,是由后端將路由列表告訴給前端注冊
?????? 啊樂同學(xué): 如果這個(gè)時(shí)候我退出登錄了,然后沒有刷新頁面,重新登錄另一個(gè)不同權(quán)限的用戶,那豈不是路由會重復(fù)?
?
答:你在路由文件中定義resetRouter的方法,新建一個(gè)全新的 Router,然后將新的 Router.matcher 給當(dāng)前的Router,在登出的模塊中調(diào)用resetRouter方法

總結(jié):
beforeEach是需要靠我們手動去幫 vue-router “辨別哪些頁面可以訪問,哪些不可以 ”addRoutes則是通過注入路由配置告訴 vue-router “我就只認(rèn)這些路由,其它路由地址跟我無關(guān)”
2.視圖層面
?上一節(jié)聊的路由方面的權(quán)限控制,主要在控制菜單頁面權(quán)限,那如果是按鈕權(quán)限,應(yīng)該怎么做?比如頁面中的按鈕 (增、刪、改、查)的權(quán)限控制是否顯示
?
2.1 指令控制
?可以結(jié)合vue的自定義指令,實(shí)現(xiàn)一個(gè)權(quán)限指令比如
?v-auth來控制權(quán)限,來判斷對應(yīng)模塊是否擁有某個(gè)權(quán)限時(shí),如果沒有則移除當(dāng)前按鈕dom元素,下面我們看下這個(gè)實(shí)現(xiàn)方式??

通過自定義權(quán)限指令v-auth來實(shí)現(xiàn)按鈕權(quán)限控制,通過傳入權(quán)限角色數(shù)組列表,來控制元素是否顯示
?????? 啊樂同學(xué): 為啥不直接用
?v-if或者v-show去控制顯示隱藏,而是自定義指令?
答:因?yàn)?v-show 的話,dom其實(shí)沒有隱藏,用戶可以改變display就看到,v-if呢,則是刪除之后會遺留備注<!-- -->
思考?? : 如果要實(shí)現(xiàn)按鈕顯示但是禁用的情況,上面的例子應(yīng)該如何修改?
?? 推薦閱讀:
vue-element-admin后臺前端解決方案 手摸手,帶你用vue擼后臺 系列二(登錄權(quán)限篇)
3.接口層面
?我們在項(xiàng)目使用中,請求庫以axios較多,我們通常會使用axios的API
?axios.interceptors.request.use也就是攔截器來做權(quán)限管理
請求頭添加 token認(rèn)證,或者也可以直接使用cookie中的授權(quán)信息,前提是要配置
withCredentials為true,也就是axios.defaults.withCredentials = true, 開啟withCredentials后,服務(wù)器才能拿到你的cookie
攔截器攔截接口返回結(jié)果,比如401沒有登錄權(quán)限。

END


