先後端分離場景下前端權限控制的理論實現

注: 本文沒具體具體,僅僅討論的是理論上存在的實現方案。

前言

如今基於 先後端分離模式的前端工程是愈來愈多了,不少公司都逐漸接受、引入實踐先後端分離的開發模式。不能否認,先後端分離的模式給予了先後端協做一個新的解決方案,而前端框架的百花齊放以及 Nodejs 的普及、踏入服務器開發的領域等等也爲先後端分離引入了新鮮的玩法。但同時也給了前端新的挑戰,前端工程化、基礎建設等問題也都逐漸凸現出來;而在不少業務中的問題也都由服務器開發人員前移到了客戶端開發人員(大部分指前端工程師)處理。html

權限的定義

權限問題一直是一些企事業後臺等項目必須面對的問題。之前的權限基本都是由後端開發人員設計維護而且處理在 view 上邏輯處理。 先後端分離開發以後勢必就出現了權限系統分離的問題。因爲權限的問題比較敏感,尤爲是涉及金錢和隱私的數據時候,本質上都是不容許用戶跨權限的訪問;對於開發人員既要保證權限系統的健壯性、安全性,也要平衡好開發階段、維護階段的迭代訴求。前端

權限控制的粒度在每一個項目中都是不同的,但大致能夠劃分爲 路由級別權限元素級別權限vue

路由級別權限的權限很容易理解,是指基於 URL 的權限控制,好比 管理員用戶能夠訪問 a.html ,而普通用戶則不容許訪問 a.html ; 而 元素級別權限 則是基於權限控制到用戶是否能夠看到、使用頁面上某個元素,好比一個輸入框、一個按鈕。一旦用戶能夠繞過權限系統跨權限的訪問不屬於本身的信息,那麼系統徹底可能被摧毀,丟失數據、數據錯誤等等,形成不可估量的損失。angularjs

拋開權限設計的複雜度而言,權限反映到 UI 上的話只有 可用不可用 的分別。在基於 RBAC 權限設計中,通常包含如下三種角色:express

  • User,即用戶,好比張3、李四等
  • Role,即角色,好比經理、副經理、普通職員等
  • Permission,即權限,權限通常和實際可執行的操做或者菜單選項直接一一映射,好比操做打印機、審批請假單等,權限直接操做的對象就是資源(好比在開放平臺中API接口是一種資源)

img

再複雜一點的,可能會引入用戶組的概念,將用戶和用戶組關聯,用戶組和角色關聯,進而關聯權限信息等到一個用戶組下面某個用戶權限信息。後端

路由權限

在基於路由的權限中,在進入路由以前咱們必須進行權限的校驗,校驗經過則可正常進入路由,不然拒絕進入並予以降級處理。前端工程化

在先後端分離這種狀況中,因爲路由已經脫離了後端的管理(即前端路由),因此大部分時候權限問題都只能由前端來處理。好在 vue 也好、angular 也好、 React 也好,都提供了 路由鉤子,容許咱們在鉤子中處理一些業務,(page.js 沒有 hooks 的設計,可是它容許咱們註冊多個 callbackcallback 按序執行,和expressrouter 設計很像 )。瀏覽器

  1. 前端本地校驗

在前端本地校驗路由權限,則要求前端持有權限信息:用戶的角色和角色的權限,在 hooks 裏利用這些信息去作校驗。這樣的好處在於減小了 接口的交互,對於體驗會有所提高 ;但也勢必引入另一個問題:數據安全問題。權限信息由前端持有,如何保證數據的安全性則是一個細細考慮的問題。緩存

這種狀況下,一種須要後端配置,權限和路由關係由後端保存持有,初始化成功後,前端動態去後端獲取權限信息緩存下來,權限設計比較複雜的狀況下,這種方案可能來講會比較好;而另一種就是權限信息自己也由前端維護,這種方案更適合權限設計比較簡單的狀況下。安全

  1. 後端動態校驗

另一種方案則是在 hooks 裏經過 接口 去後端校驗權限。這種方案中前端不須要持有路由權限問題,每次校驗都由 後端處理,前端將必要數據 post 給後端,後端去校驗權限信息, 前端再根據接口的返回作處理。這樣的話,權限的私密性得以儘量的保密,可是增長了 接口交互的過程,體驗上可能會打折扣。

固然,上面兩種方案也能夠結合起來使用,前端作一次 緩存,對於校驗過的路由前端緩存一次,再次訪問的時候先判斷本地權限信息,有的話使用本地的信息,反之則經過後端校驗。

兩種方案設計和實現上沒有什麼本質差異,也沒有誰比誰更好的區別。經過哪一種方案實現,是一個綜合考慮的問題,好比權限設計的複雜度、權限信息的敏感度等等。

還有一種特殊的設計即路由依舊是後端管理,前端的頁面只作了模板渲染的業務。每次路由跳轉都請求到了後端 , 再由後端決定渲染哪一個模板。這種狀況下則能夠直接由後端去處理權限。

元素權限

元素的權限控制比路由權限相對來講複雜一些,粒度細化到了 頁面的上的元素,也許用戶能夠看到這個頁面,可是看不到頁面上的某個按鈕。

這種狀況的權限,通常很容易想到的模板表達式,即經過模板的邏輯判斷來控制元素的隱藏顯示。

<div>
    <!-- 經過 checkAuth 函數來校驗權限 -->
    <button v-if="checkAuth()">刪除</button>
</div>

這種方案多是最簡單粗暴的解決方案了。可是它也有一些弊端:

  1. 前端必須知道權限信息
  2. 前端必須在須要控制的地方都加上判斷
  3. 有心人能夠經過模板源碼反推出一些信息。

由於涉及到了前端持有權限的問題,也面臨了和 路有權限同樣的問題:數據安全和權限複雜度。

因此還有另一種方案:預生成,在構建階段或者在線上預生成模板。經過模板標記的形式,由工具動態的生成代碼出來,這樣頁面上不存在邏輯判斷,前端拿到的模板就是最終的模板,直接渲染數據便可。

<div>
   <!-- @auth:editor admin  -->
   <button>編輯</button>
   <!-- @auth:editor admin  -->
   
   <!-- @auth:root -->
   <button>刪除</button>
   <!-- @auth:root -->
   
   <button>閱讀</button>
</div>

在模板上經過打標記的形式標記出權限差別區,再經過工具生成對應的不一樣權限的模板,最終返回給前端進行渲染。

這裏不論是在前端構建期處理仍是在服務器上訪問時候生成理論上都是能夠的,對最終結果不影響。

固然,預生成的方案只是個理論,在實踐上仍是有不少東西要處理的,好比在 vueangular 中 構建以後,模板內容被轉成 js 代碼。當瀏覽器加載完 JS 代碼後,其實模板已經被下載好了,如何根據權限去加載不一樣的模板就是一個要解決問題了。

即便在 angularjs 裏,一旦模板加載過了以後,就會被緩存在本地了,如何刷新也是一個問題。

結束

亂七八糟的算是結束了。先後端分離的狀況下,一些之前前端未曾處理的問題都會被拋出來要解決,而因爲前端的特殊性(跑在客戶端),不少東西就會受到制肘,不能直接拿後端的方案來套。固然很大程度上,前端的一些東西仍是能夠去借鑑後端的設計和理念。

對於權限的問題,不論是在後端仍是前端,始終都是一個大而廣的問題,不是一句兩句話能夠講清道明的,也不是多少代碼量就能夠解決的問題?權限也好、數據也好¿

即便拋開權限問題來講,前端的安全性都是須要時時刻刻關注的問題,權限也好、數據也好,用戶都是不可信任的。

相關文章
相關標籤/搜索