淺談Spring Cloud下微服務(wù)權(quán)限方案
背景
從傳統(tǒng)的單體應(yīng)用轉(zhuǎn)型Spring Cloud的朋友都在問我,Spring Cloud下的微服務(wù)權(quán)限怎么管?怎么設(shè)計比較合理?從大層面講叫服務(wù)權(quán)限,往小處拆分,分別為三塊:用戶認(rèn)證、用戶權(quán)限、服務(wù)校驗。
用戶認(rèn)證
傳統(tǒng)的單體應(yīng)用可能習(xí)慣了session的存在,而到了Spring cloud的微服務(wù)化后,session雖然可以采取分布式會話來解決,但終究不是上上策。開始有人推行Spring Cloud Security結(jié)合很好的OAuth2,后面為了優(yōu)化OAuth 2中Access Token的存儲問題,提高后端服務(wù)的可用性和擴展性,有了更好Token驗證方式JWT(JSON Web Token)。這里要強調(diào)一點的是,OAuth2和JWT這兩個根本沒有可比性,是兩個完全不同的東西。
OAuth2是一種授權(quán)框架,而JWT是一種認(rèn)證協(xié)議
OAuth2認(rèn)證框架OAuth2中包含四個角色:
- 資源擁有者(Resource Owner)
- 資源服務(wù)器(Resource Server)
- 授權(quán)服務(wù)器(Authorization Server)
- 客戶端(Client)
OAuth2包含4種授權(quán)模式
- 授權(quán)碼(認(rèn)證碼)模式 (Authorization code)
- 簡化(隱形)模式 (Impilict
- 用戶名密碼模式 (Resource Owner Password Credential)
- 客戶端模式 (Client Credential)
其中,OAuth2的運行流程如下圖,摘自RFC 6749:
+--------+ +---------------+ | |--(A)- Authorization Request ->| Resource | | | | Owner | | |<-(B)-- Authorization Grant ---| | | | +---------------+ | | | | +---------------+ | |--(C)-- Authorization Grant -->| Authorization | | Client | | Server | | |<-(D)----- Access Token -------| | | | +---------------+ | | | | +---------------+ | |--(E)----- Access Token ------>| Resource | | | | Server | | |<-(F)--- Protected Resource ---| | +--------+ +---------------+
我們在Spring Cloud OAuth2中,所有訪問微服務(wù)資源的請求都在Http Header中攜帶Token,被訪問的服務(wù)接下來再去請求授權(quán)服務(wù)器驗證Token的有效性,目前這種方式,我們需要兩次或者更多次的請求,所有的Token有效性校驗都落在的授權(quán)服務(wù)器上,對于我們系統(tǒng)的水平擴展成為一個非常大的瓶頸。
JWT認(rèn)證協(xié)議
授權(quán)服務(wù)器將用戶信息和授權(quán)范圍序列化后放入一個JSON字符串,然后使用Base64進行編碼,最終在授權(quán)服務(wù)器用私鑰對這個字符串進行簽名,得到一個JSON Web Token。
假設(shè)其他所有的資源服務(wù)器都將持有一個RSA公鑰,當(dāng)資源服務(wù)器接收到這個在Http Header中存有Token的請求,資源服務(wù)器就可以拿到這個Token,并驗證它是否使用正確的私鑰簽名(是否經(jīng)過授權(quán)服務(wù)器簽名,也就是驗簽)。驗簽通過,反序列化后就拿到Toekn中包含的有效驗證信息。
其中,主體運作流程圖如下:
+-----------+ +-------------+ | | 1-Request Authorization | | | |------------------------------------>| | | | grant_type&username&password | |--+ | | |Authorization| | 2-Gen | | |Service | | JWT | | 3-Response Authorization | |<-+ | |<------------------------------------| Private Key | | | access_token / refresh_token | | | | token_type / expire_in | | | Client | +-------------+ | | | | +-------------+ | | 4-Request Resource | | | |-----------------------------------> | | | | Authorization: bearer Access Token | |--+ | | | Resource | | 5-Verify | | | Service | | Token | | 6-Response Resource | |<-+ | |<----------------------------------- | Public Key | +-----------+ +-------------+
通過上述的方式,我們可以很好地完成服務(wù)化后的用戶認(rèn)證。
用戶權(quán)限
傳統(tǒng)的單體應(yīng)用的權(quán)限攔截,大家都喜歡shiro,而且用的頗為順手。可是一旦拆分后,這權(quán)限開始分散在各個API了,shiro還好使嗎?筆者在項目中,并沒有用shiro。前后端分離后,交互都是token,后端的服務(wù)無狀態(tài)化,前端按鈕資源化,權(quán)限放哪兒管好使?
抽象與設(shè)計
在介紹靈活的核心設(shè)計前,先給大家普及一個入門的概念:RBAC(Role-Based Access Control,基于角色的訪問控制),就是用戶通過角色與權(quán)限進行關(guān)聯(lián)。簡單地說,一個用戶擁有若干角色,每一個角色擁有若干權(quán)限。
RBAC其實是一種分析模型,主要分為:基本模型RBAC0(Core RBAC)、角色分層模型RBAC1(Hierarchal RBAC)、角色限制模型RBAC2(Constraint RBAC)和統(tǒng)一模型RBAC3(Combines RBAC)。
核心UML
這是筆者通過多種業(yè)務(wù)場景后抽象的RBAC關(guān)系圖
類說明
Group
群或組,擁有一定數(shù)量權(quán)限的集合,亦可以是權(quán)限的載體。
子類:User(用戶)、Role(角色)、Position(崗位)、Unit(部門),通過用戶的特定構(gòu)成,形成不同業(yè)務(wù)場景的群或組,而通過對群或組的父類授權(quán),完成了用戶的權(quán)限獲取。
Permission
權(quán)限,擁有一定數(shù)量資源的集成,亦可以是資源的載體。
Resources
權(quán)限下有資源,資源的來源有:Menu(菜單)、Button(動作權(quán)限)、頁面元素(按鈕、tab等)、數(shù)據(jù)權(quán)限等
Program
程序,相關(guān)權(quán)限控制的呈現(xiàn)載體,可以在多個菜單中掛載。
常見web程序基本構(gòu)成

模型與微服務(wù)的關(guān)系
如果把Spring Cloud服務(wù)化后的所有api接口都定義為上文的Resources,那么我們可以看到這么一個情況。
比如一個用戶的增刪改查,我們的頁面會這么做

| 頁面元素 | 資源編碼 | 資源URI | 資源請求方式 |
|---|---|---|---|
| 查詢 | user_btn_get | /api/user/{id} | GET |
| 增加 | user_btn_add | /api/user | POST |
| 編輯 | user_btn_edit | /api/user/{id} | PUT |
| 刪除 | user_btn_del | /api/user/{id} | DELETE |
在抽象成上述的映射關(guān)系后,我們的前后端的資源有了參照,我們對于用戶組的權(quán)限授權(quán)就容易了。比如我授予一個用戶增加、刪除權(quán)限。在前端我們只需要檢驗該資源編碼的有無就可以控制按鈕的顯示和隱藏,而在后端我們只需要統(tǒng)一攔截判斷該用戶是否具有URI和對應(yīng)請求方式即可。
至于權(quán)限的統(tǒng)一攔截是放置在Zuul這個網(wǎng)關(guān)上,還是落在具體的后端服務(wù)的攔截器上(Filter、Inteceptor),都可以輕而易舉地實現(xiàn)。不在局限于代碼的侵入性。放置Zuul流程圖如下:

要是權(quán)限的統(tǒng)一攔截放置在Zuul上,會有一個問題,那就是后端服務(wù)安不安全,服務(wù)只需要通過注冊中心,即可對其他服務(wù)進行調(diào)用。這里就涉及到后面的第三個模塊,服務(wù)之間的鑒權(quán)。
服務(wù)之間的鑒權(quán)
因為我們都知道服務(wù)之間開源通過注冊中心尋到客戶端后,直接遠(yuǎn)程過程調(diào)用的。對于生產(chǎn)上的各個服務(wù),一個個敏感性的接口,我們更是需要加以保護。主題的流程如下圖:

筆者的實現(xiàn)方式是基于Spring Cloud的FeignClient Inteceprot(自動申請服務(wù)token、傳遞當(dāng)前上下文)和Mvc Inteceptor(服務(wù)token校驗、更新當(dāng)前上下文)來實現(xiàn),從而對服務(wù)的安全性做進一步保護。
結(jié)合Spring Cloud的特性后,整體流程圖如下:

優(yōu)化點
雖然通過上述的用戶合法性檢驗、用戶權(quán)限攔截以及服務(wù)之間的鑒權(quán),保證了Api接口的安全性,但是其間的Http訪問頻率是比較高的,請求數(shù)量上來的時候,慢的問題是就會特別明顯??梢钥紤]一定的優(yōu)化策略,比如用戶權(quán)限緩存、服務(wù)授權(quán)信息的派發(fā)與混存、定時刷新服務(wù)鑒權(quán)Token等。
結(jié)語
上述是筆者在項目里的大體思路,有興趣的朋友可以借鑒我的開源項目,歡迎star:
- gitchina:https://gitee.com/minull/ace-security(Jwt、用戶權(quán)限)
- github:https://github.com/wxiaoqi/ace-security
- gitchina:http://git.oschina.net/geek_qi/ace-gate(服務(wù)鑒權(quán))
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringMVC使用MultipartFile 實現(xiàn)異步上傳方法介紹
這篇文章主要介紹了SpringMVC使用MultipartFile 實現(xiàn)異步上傳方法介紹,涉及pom依賴的添加,配置文件的修改等具體操作代碼,需要的朋友可以了解下。2017-09-09
java導(dǎo)出數(shù)據(jù)庫的全部表到excel
這篇文章主要為大家詳細(xì)介紹了java導(dǎo)出數(shù)據(jù)庫的全部表到excel的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-03-03
Spring Boot3整合Mybatis Plus的詳細(xì)過程(數(shù)據(jù)庫為MySQL)
這篇文章主要介紹了Spring Boot3整合Mybatis Plus的詳細(xì)過程(數(shù)據(jù)庫為MySQL),本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-07-07

