vuejs單頁應用的許可權管理實踐

2021-09-11 14:14:56 字數 3698 閱讀 2193

在眾多的b端應用中,簡單如小型企業的管理後台,還是大型的cms,crm系統,許可權管理都是乙個重中之重的需求,過往的web應用大多採取服務端模板+服務端路由的模式,許可權管理自然也由服務端進行控制和過濾.但是在前後端分離的大潮下,如果採用單頁應用開發模式的話,前端也無可避免要配合服務端共同進行許可權管理,接下來會以vuejs開發單頁應用為例,給出一些嘗試方案,希望也能給大家提供一些思路.注意採用nodejs作為中間層的前後端分離不在此文討論範圍.

關於許可權管理,由於本人對服務端並不能算得上十分了解,我只能從我以往的專案經驗中進行總結,並不一定十分準確.

一般許可權管理分為以下幾部分.

接下來會逐一講解上述部分.完整的例項**託管在github-funkylover/vue-permission-control-demo上.

首先應用使用權其實就是簡單的判斷登入狀態而已.在很多c端應用,登入之後能使用更多的功能在一定程度上也可以算作許可權管理的一部分.而在b端應用中一般表現為不登入則不能使用(當然還能使用類似找回密碼之類的功能).

以往登入狀態的保持一般通過session+cookie/token管理,使用者在開啟網頁時就帶上cookie/token,由後端邏輯判斷並進行重定向.在spa的模式下,頁面跳轉是由前端路由進行控制的,使用者狀態的判斷則需要由前端主動傳送一次自動登入的請求,根據返回結果進行跳轉.

這個自動登入的邏輯可以深挖做出多種實現,例如登入成功之後把使用者資訊加密並通過localstorage在多個tab之間公用,這樣再新開啟tab時就不需要再次自動登入.這裡就以最簡單的實現來進行講解,基本流程如下:

使用者請求頁面資源

檢查本地cookie/localstorage是否有token

如果沒有token,不管使用者請求開啟的是哪個路由,都一律跳轉到login路由

如果檢查到token,先請求自動登入的介面,根據返回的結果判斷是進入使用者請求的路由還是跳轉到login路由

而關於使用者狀態的判斷,一般應該針對進入login路由(包括忘記密碼之類的路由)和進入其他路由進行判斷,在基於[email protected]的前提下,可以在router的beforeeach鉤子上進行使用者狀態判斷並切換路由即可.下面給出部分**:

const routes = [

, ,

]},

]const router = new router()

router.beforeeach((to, from, next) => else

} else else

}})複製**

在設定好跳轉邏輯後,我們則需要在login路由中檢查是否有token並進行自動登入

// login.vueasync mounted ()  = await axios.post('/api/loginbytoken', )

if (data.ok) else

}},methods: = await axios.post('/api/login', )

if (data.ok) else

}}複製**

同理退出登入時把token置空即可.注意這裡給出的邏輯實現相對粗糙,實際應該根據需求進行改動,例如在進行自動登入的時候給使用者適當的提示,把讀取/儲存token的邏輯放進store中進行統一管理,處理token的過時邏輯等.

這裡可以借助vue-router/路由獨享的守衛來進行處理.基本思路為在每乙個需要檢查許可權的路由中設定beforeenter鉤子函式,並在其中對使用者的許可權進行判斷.

const routes = [

, }, }]

}, ]複製**

上面**是足以完成需求的,再配合上vue-router/路由懶載入也可以實現對於沒有許可權的路由不會載入相應頁面元件的資源.不過上述實現還是有一些問題.

當頁面許可權足夠細緻時,router的配置將會變得更加龐大難以維護

每當後台更新頁面許可權規則時,前端的判斷邏輯也要跟著改變,這就相當於前後端需要共同維護一套頁面級別許可權.

第乙個問題尚且可以通過編碼手段來減輕,例如把邏輯放到beforeeach鉤子中,又或者借助高階函式對許可權檢查邏輯進行抽象.但是第二個問題卻是無可避免的,如果我們只在後端進行路由的配置,而前端根據後端返回的配置擴充套件router呢,這樣就可以避免在前後端共同維護一套邏輯了,根據這個思路我們對之前邏輯進行一下改寫.

// login.vueasync mounted ()  = await axios.post('/api/loginbytoken', )

if (data.ok)

}},// ...

methods: ]}

]routes.foreach(r => )

})this.$router.addroutes(routers)

this.$router.push('/')

}}複製**

這樣就實現了根據後端的返回動態擴充套件路由,當然也可以根據後端的返回生成側欄或頂欄的導航選單,這樣就不需要再在前端處理頁面許可權了.這裡還是要再提醒一下,本文的例子只實現最基本的功能,省略了很多可優化的邏輯

每開啟新的tab(非login路由)時都會重新自動登入並重新擴充套件router

每開啟新的tab,自動登入之後依然會跳轉到/路由,就算新開啟的url為/page1

解決思路是把使用者登入資訊和路由資訊儲存在localstorage中,當開啟新tab時直接通過localstorage中儲存的資訊直接生成router物件.借助store.js和vuex-shared-mutations一類的外掛程式可以一定程度上簡化這部分邏輯,這裡不展開討論.

模組級別的許可權很好理解,其實就是帶許可權判斷的元件.在react中借助高階元件來定義需要過濾許可權的元件是非常簡單且容易理解的.請看下面的例子

const withauth = (comp, auth) => 

checkauth ()

render () else }}}

複製**

上面的例子展示的就是有許可權時展示該元件,沒有許可權時則隱藏元件們可以根據不同許可權過濾需求來定義各種高階元件來處理.

而在vuejs中可以使用通過render函式來實現

// auth.vue

import from 'vuex'

export default else

},props: ,

computed:

}// 使用

複製**

vuejs中的render函式提供完全程式設計的能力,甚至還能在render函式使用jsx語法,獲得接近react的開發體驗,詳情參考vuejs文件/渲染函式&jsx.

介面級別的許可權一般就與ui庫關聯不大,這裡簡單講一下如何處理.

首先從後端獲取允許當前使用者訪問的api介面的許可權

根據返回來的結果配置前端的ajax請求庫(如axios)的***

在***中判斷許可權,根據需求提示使用者即可

axios.interceptors.request.use((config) => else }, err => )

其實個人認為前端也不一定有必要對請求的api進行許可權判斷,畢竟介面不像路由,路由現在已經由前端來管理了,但是介面最終都需要通過伺服器的校驗.可以視需求加上.

Vue單頁及多頁應用全域性配置404頁面實踐記錄

無論單頁還是多頁,我的實現思路是總體配置404頁面的思路就是在前端路由表中新增乙個 path 404 的路由,渲染相應的404頁面。這篇文章主要介紹了vue單頁及多頁應用全域性配置404頁面實踐,需要的朋友可以參考下 前後端分離後,控制路由跳轉的責任轉移到了前端,後端只負責給前端返回乙個html文件...

簡述單頁應用的優缺點

3 單頁應用沒有頁面之間的切換,就不會出現 白屏現象 也不會出現假死並有 閃爍 現象。4 單頁應用相對伺服器壓力小,伺服器只用出資料就可以,不用管展示邏輯和頁面合成,吞吐能力會提高幾倍。5 良好的前後端分離。後端不再負責模板渲染 輸出頁面工作,後端api通用化,即同一套後端程式 不用修改就可以用於w...

Vue cli安裝方法和單頁改為多頁應用的記錄

其實把vue腳手架 vue cli 從單頁改為多頁,在網上有很多的教程。大佬請路過 我就做個記錄,以免以後會用到,如果能幫到其他人的更好。不廢話了,進入正題。node安裝好了之後就可搭建vue cli了,在安裝之前先檢查node版本,最好是最新的版本,不然用老版本的話會出現一些意想不到的驚喜。可以 ...