前后端分離 權(quán)限控制

前后端分離模式下的權(quán)限設(shè)計方案? https://mp.weixin.qq.com/s/OGyMUWXB3DuvNv-MGsbKiA

來源:www.cnblogs.com/liuyh/p/8027833.html

前后端分離模式下,所有的交互場景都變成了數(shù)據(jù),傳統(tǒng)業(yè)務(wù)系統(tǒng)中的權(quán)限控制方案在前端已經(jīng)不再適用,因此引發(fā)了我對權(quán)限的重新思考與設(shè)計。

權(quán)限控制到底控制的是什么?

在理解權(quán)限控制之前,需要明白兩個概念:資源和權(quán)限。什么是資源,對于一個系統(tǒng)來說,系統(tǒng)內(nèi)部的所有信息都可以理解為這個系統(tǒng)的資源。頁面是資源、數(shù)據(jù)是資源、按鈕是資源、圖片是資源、甚至頁面上一條分割線也可理解為是這個系統(tǒng)的資源。

而權(quán)限就是訪問某個資源所需要的標(biāo)識。無論系統(tǒng)的權(quán)限如何設(shè)計,在用戶登錄時,都可以計算得出用戶所擁有的權(quán)限標(biāo)識集合,也就確定了該用戶能訪問哪些系統(tǒng)資源,這就是我理解的權(quán)限控制的本質(zhì)。于是我們可以得出:權(quán)限控制是控制登錄用戶對于系統(tǒng)資源的訪問。

前后端分離模式下,前后端在權(quán)限控制中各自的職責(zé)是什么?

在弄清前后端在權(quán)限控制中各自的職責(zé)是什么之前,需要理解前后端各自在系統(tǒng)中的職責(zé)。這個還是很好理解:

服務(wù)端:提供數(shù)據(jù)接口。

前端:路由控制、頁面渲染。

由于前端負(fù)責(zé)與用戶交互,用戶所能操作的資源入口都是由前端進(jìn)行控制,那么前端的權(quán)限控制就包括:

前端路由的權(quán)限控制,過濾非法請求,用戶只能訪問權(quán)限范圍內(nèi)的頁面資源。

頁面內(nèi)組件的權(quán)限控制,根據(jù)用戶的權(quán)限控制頁面組件的渲染。包括各種按鈕、表格、分割線等。

隨著前端組件化的快速發(fā)展,用戶所看到的一切均可理解為組件,頁面是個大組件,其內(nèi)部由各個小組件拼湊而來,那么前端權(quán)限控制最終落地到對組件的權(quán)限控制。于是腦補了出了最優(yōu)雅的權(quán)限組件使用方式:

<組件permissionName='xxx'/>

前端可以渲染出用戶權(quán)限范圍內(nèi)的各種系統(tǒng)資源,但是不能保證數(shù)據(jù)接口的安全性,某些比較喜歡折騰的用戶完全可以越過前端的頁面訪問我們系統(tǒng)的數(shù)據(jù)接口,那么服務(wù)端的權(quán)限控制最終落地到對接口的權(quán)限驗證。

實現(xiàn)思路

引上文,系統(tǒng)的一切資源均可進(jìn)行權(quán)限控制,實際上也可以做到,但在我們實際的操作過程中,往往不需要細(xì)化到分割線那種程度。這里以按鈕級權(quán)限控制為例做實現(xiàn)說明,如果有更細(xì)粒度的權(quán)限需求,此思路依然可行。

前端路由權(quán)限控制。用戶登錄時拿到用戶擁有的權(quán)限標(biāo)識集合,在前端存儲。路由變化時,進(jìn)行權(quán)限判斷,通過則渲染對應(yīng)頁面組件,否則渲染403組件。示例代碼:

let hasPermission?=?permission.check(current.permissionName);

{hasPermission???children?:}

封裝bird-button權(quán)限按鈕組件,傳入按鈕所需權(quán)限名,內(nèi)部進(jìn)行權(quán)限判斷,通過則渲染按鈕。

測試按鈕

服務(wù)端。服務(wù)端權(quán)限驗證很好理解。使用攔截器驗證當(dāng)前請求的權(quán)限。代碼示例:

publicclassSsoAuthorizeInterceptorextendsHandlerInterceptorAdapter{

@Autowired

privateTicketHandler?ticketHandler;

@Autowired

privateSsoAuthorizeManager?authorizeManager;

@Override

publicbooleanpreHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)throwsException{

if(!(handlerinstanceofHandlerMethod))returnfalse;

HandlerMethod?handlerMethod?=?(HandlerMethod)?handler;

SsoAuthorize?authorize?=?handlerMethod.getMethodAnnotation(SsoAuthorize.class);

if(authorize?!=null)?{

TicketInfo?ticketInfo?=?ticketHandler.getTicket(request);

if(ticketInfo?==null)?{

thrownewUnAuthorizedException("用戶信息已失效.");

}

String[]?requirePermissions?=?authorize.permissions();

if(requirePermissions.length==0)returntrue;

booleanisCheckAll?=?authorize.isCheckAll();

UserPermissionChecker?permissionChecker?=?authorizeManager.getUserPermissionChecker();

if(!permissionChecker.hasPermissions(ticketInfo.getUserId(),requirePermissions,isCheckAll)){

thrownewForbiddenException("用戶沒有當(dāng)前操作的權(quán)限.");

}

}

returntrue;

}

}

源碼地址

本博客涉及到的前端權(quán)限控制思路均已在:

https://github.com/liuxx001/bird-front

項目中實現(xiàn),項目中除了按鈕級權(quán)限方案還提供了后臺業(yè)務(wù)系統(tǒng)開發(fā)中常用的數(shù)據(jù)組件,包括:

下拉選擇器:bird-selector。

https://github.com/liuxx001/bird-front/blob/master/doc/bird-selector.md

全自動數(shù)據(jù)表格:bird-grid。

https://github.com/liuxx001/bird-front/blob/master/doc/bird-grid.md

全自動樹表:bird-tree-grid。

https://github.com/liuxx001/bird-front/blob/master/doc/bird-tree-grid.md

數(shù)據(jù)樹:bird-tree。

https://github.com/liuxx001/bird-front/blob/master/doc/bird-tree.md

全自動表單:bird-form。

https://github.com/liuxx001/bird-front/blob/master/doc/bird-form.md

權(quán)限按鈕:bird-button。

https://github.com/liuxx001/bird-front/blob/master/doc/bird-button.md

所有業(yè)務(wù)組件的理念均是結(jié)合服務(wù)端接口進(jìn)行組件的封裝,兼顧靈活性的同時保證更優(yōu)的業(yè)務(wù)開發(fā)速度。

歡迎指正,提出不同的看法。

(完)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容