1. 程式人生 > >Spring Cloud實戰 | 第十一篇:Spring Cloud Gateway 閘道器實現對RESTful介面許可權控制和按鈕許可權控制

Spring Cloud實戰 | 第十一篇:Spring Cloud Gateway 閘道器實現對RESTful介面許可權控制和按鈕許可權控制

## 一. 前言 hi,大家好,這應該是農曆年前的關於開源專案[有來商城](https://github.com/hxrui) 的最後一篇文章了。 [有來商城](https://github.com/hxrui) 是基於 Spring Cloud OAuth2 + Spring Cloud Gateway + JWT實現的統一認證鑑權,Spring Cloud & Alibaba + vue-element-admin實現的微服務、前後端分離的全棧開源專案。 [有來商城](https://github.com/hxrui) 的許可權設計主要是為了實現以下幾點目標: - 實現RBAC模式的許可權管理設計 - 實現基於vue-element-admin後臺選單許可權管理系統 - Spring Cloud Gateway閘道器針對RESTful介面許可權控制 - Vue自定義指令實現按鈕級別許可權控制 ## 二. 專案介紹 ### 1. 專案簡介 [有來商城](https://github.com/hxrui) 是基於Spring Boot 2.4、Spring Cloud 2020 & Alibaba、Vue、element-ui、uni-app快速構建的一套**全棧**開源商城平臺,包括微服務應用、管理平臺、微信小程式及APP應用。 ### 2. 專案地址 **專案預覽地址:** [http://www.youlai.store](https://www.youlai.store/) **微信小程式體驗碼:** ![](https://gitee.com/haoxr/image/raw/master/default/%E4%B8%89%E7%A0%81%E5%90%88%E4%B8%80.jpg) **原始碼地址:** 專案名稱 | Github | 碼雲 ---|---|--- 微服務後臺 |[youlai-mall](https://github.com/hxrui/youlai-mall) |[youlai-mall](https://gitee.com/youlaitech/youlai-mall) 管理前端 | [youlai-mall-admin](https://github.com/hxrui/youlai-mall-admin)| [youlai-mall-admin](https://gitee.com/youlaitech/youlai-mall-admin) 微信小程式 | [youlai-mall-weapp](https://github.com/hxrui/youlai-mall-weapp)| [youlai-mall-weapp](https://gitee.com/youlaitech/youlai-mall-weapp) APP應用 | [youlai-mall-app](https://github.com/hxrui/youlai-mall-app)| [youlai-mall-app](https://gitee.com/youlaitech/youlai-mall-app) ### 3. 專案往期文章 > 後臺微服務 1. [Spring Cloud實戰 | 第一篇:Windows搭建Nacos服務 ](https://www.cnblogs.com/haoxianrui/p/13581881.html) 2. [Spring Cloud實戰 | 第二篇:Spring Cloud整合Nacos實現註冊中心](https://www.cnblogs.com/haoxianrui/p/13584204.html) 3. [Spring Cloud實戰 | 第三篇:Spring Cloud整合Nacos實現配置中心](https://www.cnblogs.com/haoxianrui/p/13585125.html) 4. [Spring Cloud實戰 | 第四篇:Spring Cloud整合Gateway實現API閘道器](https://www.cnblogs.com/haoxianrui/p/13608650.html) 5. [Spring Cloud實戰 | 第五篇:Spring Cloud整合OpenFeign實現微服務之間的呼叫](https://www.cnblogs.com/haoxianrui/p/13615592.html) 6. [Spring Cloud實戰 | 第六篇:Spring Cloud Gateway+Spring Security OAuth2+JWT實現微服務統一認證授權](https://www.cnblogs.com/haoxianrui/p/13719356.html) 7. [Spring Cloud實戰 | 最七篇:Spring Cloud Gateway+Spring Security OAuth2整合統一認證授權平臺下實現登出使JWT失效方案](https://www.cnblogs.com/haoxianrui/p/13740264.html) 8. [Spring Cloud實戰 | 最八篇:Spring Cloud +Spring Security OAuth2+ Vue前後端分離模式下無感知重新整理實現JWT續期](https://www.cnblogs.com/haoxianrui/p/14022632.html) 9. [Spring Cloud實戰 | 最九篇:Spring Security OAuth2認證伺服器統一認證自定義異常處理](https://www.cnblogs.com/haoxianrui/p/14028366.html) 10. [Spring Cloud實戰 | 第十篇 :Spring Cloud + Nacos整合Seata 1.4.1最新版本實現微服務架構中的分散式事務,進階之路必須要邁過的檻](https://www.cnblogs.com/haoxianrui/p/14280184.html) > 後臺管理前端 1. [vue-element-admin實戰 | 第一篇: 移除mock接入微服務介面,搭建SpringCloud+Vue前後端分離管理平臺](https://www.cnblogs.com/haoxianrui/p/13624548.html) 2. [vue-element-admin實戰 | 第二篇: 最小改動接入後臺實現根據許可權動態載入選單](https://www.cnblogs.com/haoxianrui/p/13676619.html) > 微信小程式 1. [vue+uni-app商城實戰 | 第一篇:從0到1快速開發一個商城微信小程式,無縫接入Spring Cloud OAuth2認證授權登入](https://www.cnblogs.com/haoxianrui/p/13882310.html) > 應用部署 1. [Docker實戰 | 第一篇:Linux 安裝 Docker](https://www.cnblogs.com/haoxianrui/p/14067423.html) 2. [Docker實戰 | 第二篇:Docker部署nacos-server:1.4.0](https://www.cnblogs.com/haoxianrui/p/14059009.html) 3. [Docker實戰 | 第三篇:IDEA整合Docker外掛實現一鍵自動打包部署微服務專案,一勞永逸的技術手段值得一試](https://www.cnblogs.com/haoxianrui/p/14088400.html) 4. [Docker實戰 | 第四篇:Docker安裝Nginx,實現基於vue-element-admin框架構建的專案線上部署](https://www.cnblogs.com/haoxianrui/p/14091762.html) 5. [Docker實戰 | 第五篇:Docker啟用TLS加密解決暴露2375埠引發的安全漏洞,被黑掉三臺雲主機的教訓總結](https://www.cnblogs.com/haoxianrui/p/14095306.html) ## 三. 資料庫設計 RBAC(Role-Based Access Control)**基於角色訪問控制**,目前使用最為廣泛的許可權模型。 此模型有三個角色使用者、角色和許可權,在傳統的許可權模型使用者直接關聯加了角色層,解耦了使用者和許可權,使得許可權系統有了更清晰的職責劃分和更高的靈活度。 以下是[有來系統](https://github.com/hxrui)
關於RBAC許可權模型的資料庫 ![](https://i.loli.net/2021/02/08/kumn3iIZJ4zdcDe.png) 使用者和角色關係不用過多說明,這裡重點說下許可權,首先系統的許可權分為3類,具體如下表: 許可權名稱|表名|欄位|許可權標識 ---|---|---|--- 選單許可權|sys_menu | | 介面許可權|sys_permission|type=1|PUT_/users/** 按鈕許可權|sys_permission|type=2|system:user:add 其實瞭解過目前主流開源系統的許可權設計,大概率的把選單和按鈕放一塊然後根據類別欄位區分,以下就關於這種方式優劣發表下個人意見,僅供大家參考下不必較真: **優勢:** 1. 理論上合理,按鈕肯定屬於某個選單之下 2. 省去了許可權表(sys_permission)和關聯中間表這兩張表 **劣勢:** 1. 選單模組變的複雜了,選單表多了和選單無關聯的型別欄位和許可權標識欄位 2. 選單和按鈕查詢要區分型別,給程式碼開發帶來複雜和影響查詢效能 3. 不能同時滿足按鈕許可權控制和閘道器根據請求路徑Ant匹配鑑權(具體下文說) ## 四. 許可權管理系統 先看下vue-element-admin下的RBAC模型下的後臺許可權管理介面,體驗地址:[http://www.youlai.store](https://www.youlai.store/) - **選單許可權管理** ![](https://gitee.com/haoxr/image/raw/master/default/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20210206221810.png) - **角色分配許可權** ![](https://gitee.com/haoxr/image/raw/master/default/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20210206221757.png) ## 五. RESTful介面許可權控制 ### 1. 介面和按鈕的許可權標識的區別 上文說到的關於許可權表的拆分,選單單獨一張表,按鈕許可權和介面許可權合為一張表根據型別type欄位區分,之所以這樣因為介面和按鈕許可權有些共性,都有一個許可權標識欄位。 至於按鈕和介面為什麼要區分呢?都使用`system:user:add`許可權標識不可以嗎? 具體做法是介面方法加上Spring Security的註解@PreAuthorize("hasPermission('system:user:add')"),在執行方法前判斷使用者時候擁有該許可權。 答案是一般場景這樣設計絕對沒問題。但這裡使用閘道器作為統一鑑權的入口,肯定希望閘道器一次性把鑑權的活做的乾脆利落,這樣就不需要在各個微服務單獨的把Spring Security許可權模組引入鑑權,通過閘道器鑑權能把職責分工明確,減少開發工作量,無許可權的請求直接被閘道器攔截返回,不會走到微服務那裡再被告知無權訪問,提高請求效率。 Spring Cloud Gateway閘道器使用請求路徑Ant匹配請求標識進行許可權判斷的,例如`/users/1`經過Ant匹配到許可權標識`/users/**`,而`/users/**`是被使用者所持有的許可權標識,這就標識使用者允許訪問`/users/1`的請求,所以和按鈕的許可權標識`system:user:add`是有區別的。 這樣就完事了嗎?當然還沒,因為 [有來系統](https://github.com/hxrui) 較於其他系統它是比較嚴格遵守`REST`介面設計規範,所以如果僅僅是上面根據請求路徑URL判斷許可權肯定是不合理的,`/users/1`這個請求路徑在RESTful介面下可能是`GET`型別的請求也有可能是`PUT`型別的請求,那該如何處理? 所以在sys_permission表裡還有一個method欄位來標識請求方法型別,值可能會是*、GET、POST、PUT、PATCH、DELETE等HTTP請求方法型別,其中*是不限請求方法型別的意思,然後將請求方法型別和請求路徑組合得到介面的許可權標識是這樣的`PUT_users/1`。 接下來就通過對 [有來系統](https://github.com/hxrui) 的實戰操作來演示閘道器如何細粒度對RESTful介面的許可權控制。 ### 2. 新增許可權 新增使用者管理的增刪改查許可權 ![](https://gitee.com/haoxr/image/raw/master/default/20210210103406.png) ### 3. 角色授權 賦予系統管理員(admin)`使用者查詢`許可權,無其他許可權 ![](https://gitee.com/haoxr/image/raw/master/default/20210210124030.png) ![](https://gitee.com/haoxr/image/raw/master/default/20210210124911.png) ### 4. 載入角色許可權規則資料至快取 專案啟動檢視Redis中的角色許可權規則: ![](https://gitee.com/haoxr/image/raw/master/default/20210210131406.png) 看到系統管理員這個角色是沒有使用者修改許可權的。你可以給角色新增使用者修改許可權後嘗試是否可以修改成功。 ### 5. 介面許可權控制演示 `admin`系統管理員登入執行一個`使用者修改`的提交的請求,看一下閘道器鑑權的流程: ![](https://gitee.com/haoxr/image/raw/master/default/20210210132454.png) 結果可想而知,系統管理員不具有修改使用者`PUT_/youlai-admin/v1/users/2`許可權,從快取查詢只有超級管理員具有該介面請求方法訪問許可權。頁面結果顯示如下: ![](https://gitee.com/haoxr/image/raw/master/default/20210210132841.png) ## 六. 按鈕許可權控制 ### 1. 什麼是Vue自定義指令? Vue除了核心功能預設內建的指令 (v-model 和 v-show),Vue 也允許註冊自定義指令。 這裡主要使用`Vue.directive`註冊一個全域性自定義指令`v-has- permission`用於許可權判斷,然後在模板中的任何元素使用`v-has- permission`屬性。 [自定義指令學習傳送門](https://cn.vuejs.org/v2/guide/custom-directive.html) ### 2. 新增按鈕許可權 ![](https://gitee.com/haoxr/image/raw/master/default/20210210174833.png) ### 3. 角色授權 ![](https://gitee.com/haoxr/image/raw/master/default/20210210175343.png) ### 4. 載入角色按鈕許可權資料 完整程式碼:[youlai-mall-admin](https://github.com/hxrui/youlai-mall-admin) 登入成功時獲取使用者資訊,其中包含該使用者擁有的許可權字串集合如下: ![](https://gitee.com/haoxr/image/raw/master/default/20210210184613.png) 這裡將使用者許可權擁有的字串集合快取到vuex的perms屬性中: ![](https://gitee.com/haoxr/image/raw/master/default/20210210210607.png) ### 5. 自定義和註冊全域性指令 [有來管理前端](https://github.com/hxrui/youlai-mall-admin) 是基於`vue-element-admin`後臺前端解決方案,在`vue-element-admin`專案我們可以看到自定義指令的應用。如下: ![](https://gitee.com/haoxr/image/raw/master/default/20210210200834.png) 然後複製一份`permission.js`重新命名為`hasPermission.js`,修改後如下: ``` import store from '@/store' // 校驗使用者是否擁有按鈕許可權 function hasPermission(el, binding) { const {value} = binding const perms = store.getters && store.getters.perms if (value && value instanceof Array) { if (value.length >
0) { const requiredPerms = value const hasPermission = perms.some(perm => { return requiredPerms.includes(perm) }) if (!hasPermission) { el.parentNode && el.parentNode.removeChild(el) } } } else { throw new Error(`need perms! Like v-has-permission="['system:user:add','system:user:edit']"`) } } export default { inserted(el, binding) { hasPermission(el,binding) }, update(el, binding) { hasPermission(el,binding) } } ``` 註冊`hasPermission`至全域性指令: ![](https://gitee.com/haoxr/image/raw/master/default/20210210204858.png) ![](https://gitee.com/haoxr/image/raw/master/default/20210210205054.png) 指令在元件上的應用: ![](https://gitee.com/haoxr/image/raw/master/default/20210210205246.png) ### 6. 按鈕許可權控制演示 系統管理員是沒有`修改`按鈕的許可權的,結果如下頁面不顯示修改按鈕。 ![](https://gitee.com/haoxr/image/raw/master/default/20210210205546.png) 那給系統管理員新增`修改`按鈕的許可權,再看看使用者頁面的顯示情況 ![](https://gitee.com/haoxr/image/raw/master/default/20210210205829.png) ![](https://gitee.com/haoxr/image/raw/master/default/20210210210002.png) 此時使用者頁面的修改按鈕已經顯示出來了,至此完成了系統的按鈕許可權控制。 ## 七. 結語 本篇通過實戰的方式講述如何基於Spring Cloud Gateway + vue-element-admin技術設計一套符合RBAC規範的許可權管理系統,通過閘道器就可以輕易實現RESTful介面方法細粒度的控制,無需將Spring Security模組引入各個微服務;以及使用Vue的自定義指令在元件中使用實現細粒度的按鈕許可權控制。 如果你對此係統許可權設計有更好的建議,歡迎留言給我,在此感謝!如果對專案感興趣的話,歡迎加我微信和專案交流群。 最後預祝大家新年愉快,有個完美充實的小