阿里云優惠神卷、最高優惠25%,值得擁有:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ryr8l9eb&utm_source=ryr8l9eb
背景
從傳統的單體應用轉型Spring Cloud的朋友都在問我,Spring Cloud
下的微服務權限怎么管?怎么設計比較合理?從大層面講叫服務權限,往小處拆分,分別為三塊:用戶認證
、用戶權限
、服務校驗
。
用戶認證
傳統的單體應用可能習慣了session的存在,而到了Spring cloud的微服務化后,session雖然可以采取分布式會話來解決,但終究不是上上策。開始有人推行Spring Cloud Security結合很好的OAuth2
,后面為了優化OAuth 2中Access Token
的存儲問題,提高后端服務的可用性和擴展性,有了更好Token驗證方式JWT
(JSON Web Token)。這里要強調一點的是,OAuth2
和JWT
這兩個根本沒有可比性,是兩個完全不同的東西。
OAuth2是一種授權框架
,而JWT
是一種認證協議
OAuth2認證框架
OAuth2中包含四個角色:
- 資源擁有者(Resource Owner)
- 資源服務器(Resource Server)
- 授權服務器(Authorization Server)
- 客戶端(Client)
OAuth2包含4種授權模式
- 授權碼(認證碼)模式 (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中,所有訪問微服務資源的請求都在Http Header中攜帶Token,被訪問的服務接下來再去請求授權服務器驗證Token的有效性,目前這種方式,我們需要兩次或者更多次
的請求,所有的Token有效性校驗都落在的授權服務器上,對于我們系統的水平擴展成為一個非常大的瓶頸。
JWT認證協議
授權服務器
將用戶信息和授權范圍序列化后放入一個JSON字符串,然后使用Base64進行編碼,最終在授權服務器用私鑰對這個字符串進行簽名,得到一個JSON Web Token
。
假設其他所有的資源服務器都將持有一個RSA公鑰,當資源服務器接收到這個在Http Header中存有Token的請求,資源服務器就可以拿到這個Token,并驗證它是否使用正確的私鑰簽名(是否經過授權服務器簽名,也就是驗簽)。驗簽通過,反序列化后就拿到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 |
+-----------+ +-------------+
通過上述的方式,我們可以很好地完成服務化后的用戶認證。
用戶權限
傳統的單體應用的權限攔截,大家都喜歡shiro
,而且用的頗為順手。可是一旦拆分后,這權限開始分散在各個API了,shiro
還好使嗎?前后端分離后,交互都是token,后端的服務無狀態化,前端按鈕資源化,權限放哪兒管好使?
抽象與設計
在介紹靈活的核心設計前,先給大家普及一個入門的概念:RBAC
(Role-Based Access Control,基于角色的訪問控制),就是用戶通過角色與權限進行關聯。簡單地說,一個用戶擁有若干角色,每一個角色擁有若干權限。
RBAC其實是一種分析模型,主要分為:基本模型RBAC0(Core RBAC)、角色分層模型RBAC1(Hierarchal RBAC)、角色限制模型RBAC2(Constraint RBAC)和統一模型RBAC3(Combines RBAC)。
更多詳情大家可以了解:RBAC權限模型
核心UML
這是筆者通過多種業務場景后抽象的RBAC關系圖
類說明
- Group
群或組,擁有一定數量權限的集合,亦可以是權限的載體。
子類
:User(用戶)、Role(角色)、Position(崗位)、Unit(部門),通過用戶的特定構成,形成不同業務場景的群或組,而通過對群或組的父類授權,完成了用戶的權限獲取。
- Permission
權限,擁有一定數量資源的集成,亦可以是資源的載體。
- Resources
權限下有資源,資源的來源有:Menu(菜單)、Button(動作權限)、頁面元素(按鈕、tab等)、數據權限等
- Program
程序,相關權限控制的呈現載體,可以在多個菜單中掛載。
- 常見web程序基本構成
模型與微服務的關系
如果把Spring Cloud服務化后的所有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 |
在抽象成上述的映射關系后,我們的前后端的資源有了參照,我們對于用戶組的權限授權就容易了。比如我授予一個用戶增加、刪除權限。在前端
我們只需要檢驗該資源編碼
的有無就可以控制按鈕的顯示和隱藏,而在后端
我們只需要統一攔截判斷該用戶是否具有URI
和對應請求方式
即可。
至于權限的統一攔截是放置在Zuul
這個網關上,還是落在具體的后端服務的攔截器上(Filter、Inteceptor),都可以輕而易舉地實現。不在局限于代碼的侵入性。放置Zuul流程圖如下:
要是權限的統一攔截放置在Zuul
上,會有一個問題,那就是后端服務安不安全,服務只需要通過注冊中心,即可對其他服務進行調用。這里就涉及到后面的第三個模塊,服務之間的鑒權。
服務之間的鑒權
因為我們都知道服務之間開源通過注冊中心尋到客戶端后,直接遠程過程調用的。對于生產上的各個服務,一個個敏感性的接口,我們更是需要加以保護。主題的流程如下圖:
筆者的實現方式是基于Spring Cloud的FeignClient Inteceprot
(自動申請服務token、傳遞當前上下文)和Mvc Inteceptor
(服務token校驗、更新當前上下文)來實現,從而對服務的安全性做進一步保護。
結合Spring Cloud的特性后,整體流程圖如下:
優化點
雖然通過上述的用戶合法性檢驗、用戶權限攔截以及服務之間的鑒權,保證了Api接口的安全性,但是其間的Http訪問頻率
是比較高的,請求數量上來的時候,慢
的問題是就會特別明顯。可以考慮一定的優化策略,比如用戶權限緩存、服務授權信息的派發與混存、定時刷新服務鑒權Token等。
結語
上述是筆者在項目里的大體思路,有興趣的朋友可以借鑒我的開源項目,歡迎star:
強烈推薦
老A在CSDN上開了一門關于Spring Cloud服務化前后端分離的權限相關實戰視頻,有需要學習的朋友可以了解下
【跳過基礎】課程地址:http://edu.csdn.net/course/detail/5914
【基礎+進階】課程地址:http://edu.csdn.net/course/detail/5840
知識索取
想獲取更多微服務知識和文章,歡迎關注老A
公眾號,帶你更懂微服務。