前后端分離模式下的權(quán)限設(shè)計方案
作者 |?_liuxx
來源?|?cnblogs.com/liuyh/p/8027833.html
權(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é)是什么?
服務(wù)端:提供數(shù)據(jù)接口。
前端:路由控制、頁面渲染。
由于前端負(fù)責(zé)與用戶交互,用戶所能操作的資源入口都是由前端進行控制,那么前端的權(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)思路
前端路由權(quán)限控制。用戶登錄時拿到用戶擁有的權(quán)限標(biāo)識集合,在前端存儲。路由變化時,進行權(quán)限判斷,通過則渲染對應(yīng)頁面組件,否則渲染403組件。示例代碼:
let?hasPermission?=?permission.check(current.permissionName);
<div?className={styles.content}>
????{hasPermission???children?:?<Exception?type={403}/>}
div>封裝bird-button權(quán)限按鈕組件,傳入按鈕所需權(quán)限名,內(nèi)部進行權(quán)限判斷,通過則渲染按鈕。
<BirdButton?permissionName={'sys'}?type='primary'>測試按鈕BirdButton>服務(wù)端。服務(wù)端權(quán)限驗證很好理解。使用攔截器驗證當(dāng)前請求的權(quán)限。代碼示例:
public?class?SsoAuthorizeInterceptor?extends?HandlerInterceptorAdapter?{
????@Autowired
????private?TicketHandler?ticketHandler;
????@Autowired
????private?SsoAuthorizeManager?authorizeManager;
????@Override
????public?boolean?preHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)?throws?Exception?{
????????if?(!(handler?instanceof?HandlerMethod))?return?false;
????????HandlerMethod?handlerMethod?=?(HandlerMethod)?handler;
????????SsoAuthorize?authorize?=?handlerMethod.getMethodAnnotation(SsoAuthorize.class);
????????if?(authorize?!=?null)?{
????????????TicketInfo?ticketInfo?=?ticketHandler.getTicket(request);
????????????if?(ticketInfo?==?null)?{
????????????????throw?new?UnAuthorizedException("用戶信息已失效.");
????????????}
????????????String[]?requirePermissions?=?authorize.permissions();
????????????if(requirePermissions.length==0)return?true;
????????????boolean?isCheckAll?=?authorize.isCheckAll();
????????????UserPermissionChecker?permissionChecker?=?authorizeManager.getUserPermissionChecker();
????????????if(!permissionChecker.hasPermissions(ticketInfo.getUserId(),requirePermissions,isCheckAll)){
????????????????throw?new?ForbiddenException("用戶沒有當(dāng)前操作的權(quán)限.");
????????????}
????????}
????????return?true;
????}
}github.com/liuxx001/bird-front
項目中實現(xiàn),項目中除了按鈕級權(quán)限方案還提供了后臺業(yè)務(wù)系統(tǒng)開發(fā)中常用的數(shù)據(jù)組件,包括:
下拉選擇器:bird-selector。 github.com/liuxx001/bird-front/blob/master/doc/bird-selector.md 全自動數(shù)據(jù)表格:bird-grid。 github.com/liuxx001/bird-front/blob/master/doc/bird-grid.md 全自動樹表:bird-tree-grid。
github.com/liuxx001/bird-front/blob/master/doc/bird-tree-grid.md 數(shù)據(jù)樹:bird-tree。 github.com/liuxx001/bird-front/blob/master/doc/bird-tree.md
全自動表單:bird-form。
github.com/liuxx001/bird-front/blob/master/doc/bird-form.md
權(quán)限按鈕:bird-button。 github.com/liuxx001/bird-front/blob/master/doc/bird-button.md

如有收獲,歡迎「分享?
」
「點贊
」「評論?
」
看完本文有收獲?請轉(zhuǎn)發(fā)分享給更多人
? 開發(fā)者全社區(qū)?
