在前后端分離的模式下,所有的交互場景都變成了數據交互,因此傳統業務系統中的權限控制方案在前端已經不再適用(比如使用后台模板標簽進行權限控制),需要另外設計權限控制方案。
權限控制的概念
要理解權限控制,需要明白兩個概念:資源和權限。
資源:對於一個系統來說,系統內部的所有信息都可以理解為是這個系統的資源。頁面是資源、數據是資源、按鈕是資源、圖片也是資源。
權限:權限就是訪問某個資源所需要的標識。無論系統的權限如何設計,在用戶登陸的時候都需要計算當前登陸用戶所擁有的權限標識集合,這樣才能確定這個用戶所能訪問的系統資源。
由上面可以得出,權限控制是控制登陸用戶對於系統資源的訪問。
前后端在權限控制中各自的職責
要弄清前后端在權限控制中各自的職責,需要明白前后端在系統中各自的職責。
服務端:提供數據接口。
前端:路由控制、頁面渲染。
由於前端負責與用戶交互,這就意味着,用戶所能操作的資源入口就都是由前端進行控制,那么前端的權限控制就包括了前端路由的權限控制和頁面內組件的權限控制。
前端路由的權限控制:過濾非法請求,用戶只能訪問權限范圍之內的頁面資源。
頁面內組件的權限控制:根據用戶的權限控制頁面組件的渲染,包括各種按鈕、表格和分割線等。
隨着前端組件化的快速發展,用戶所看到的一切都可以理解為組件。頁面是一個大組件,其內部由各種小組件拼湊而來,那么前端權限的控制最終就落地到了對組件的權限控制。
<組件 permission='xxx' />
這樣,前端就可以渲染出用戶權限范圍內的各種系統資源。但是卻不能保證數據接口的安全性,因為某些比較喜歡折騰的用戶完全可以越過前端的頁面訪問系統的數據接口。服務端的權限控制最終還是要落地到對接口的權限驗證。
簡單實現
理論上來說,系統的一切資源都是可以進行權限控制的,實際上也可以做得到,只是實際場景中並不需要細化到頁面上一條分割線這種程度,最細的粒度一般只是到按鈕級別。
前端
前端路由權限控制,可以通過在用戶登陸的時候存儲在前端的用戶所擁有的權限標識集合,在路由變化時進行權限判斷。具體是,權限驗證通過則渲染對應頁面,否則渲染403組件。
let hasPermission = permission.check(current.permissionName); <div className={styles.content}> {hasPermission ? children : <Exception type={403}/>} </div>
服務端
服務端的權限驗證很好理解,一個最簡單的實現是使用攔截器驗證當前請求的權限。
public class SsoAuthorizeInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 校驗權限 } }
總結
所有業務組件的設計理念均是要結合服務端接口進行組件的封裝,兼顧靈活性的同時可以保證更優的業務開發速度。
"不可能實現的諾言最動人。"
