背景
從傳統的單體應用轉型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是一種認證協議git
OAuth2認證框架
OAuth2中包含四個角色:
資源擁有者(Resource Owner)
資源服務器(Resource Server)
受權服務器(Authorization Server)
客戶端(Client)
OAuth2包含4種受權模式
受權碼(認證碼)模式 (Authorization code)
簡化(隱形)模式 (Impilict
用戶名密碼模式 (Resource Owner Password Credential)
客戶端模式 (Client Credential)
其中,OAuth2的運行流程以下圖,摘自RFC 6749:github
+--------+ +---------------+
| |--(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 ---| |
+--------+ +---------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
咱們在Spring Cloud OAuth2中,全部訪問微服務資源的請求都在Http Header中攜帶Token,被訪問的服務接下來再去請求受權服務器驗證Token的有效性,目前這種方式,咱們須要兩次或者更屢次的請求,全部的Token有效性校驗都落在的受權服務器上,對於咱們系統的水平擴展成爲一個很是大的瓶頸。web
JWT認證協議
受權服務器將用戶信息和受權範圍序列化後放入一個JSON字符串,而後使用Base64進行編碼,最終在受權服務器用私鑰對這個字符串進行簽名,獲得一個JSON Web Token。後端
假設其餘全部的資源服務器都將持有一個RSA公鑰,當資源服務器接收到這個在Http Header中存有Token的請求,資源服務器就能夠拿到這個Token,並驗證它是否使用正確的私鑰簽名(是否通過受權服務器簽名,也就是驗籤)。驗籤經過,反序列化後就拿到Toekn中包含的有效驗證信息。api
其中,主體運做流程圖以下:緩存
+-----------+ +-------------+
| | 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 |
+-----------+ +-------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
經過上述的方式,咱們能夠很好地完成服務化後的用戶認證。安全
用戶權限
傳統的單體應用的權限攔截,你們都喜歡shiro,並且用的頗爲順手。但是一旦拆分後,這權限開始分散在各個API了,shiro還好使嗎?筆者在項目中,並無用shiro。先後端分離後,交互都是token,後端的服務無狀態化,前端按鈕資源化,權限放哪兒管好使?服務器
抽象與設計
在介紹靈活的核心設計前,先給你們普及一個入門的概念:RBAC(Role-Based Access Control,基於角色的訪問控制),就是用戶經過角色與權限進行關聯。簡單地說,一個用戶擁有若干角色,每個角色擁有若干權限。session
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: - gitchina:https://gitee.com/minull/ace-security(Jwt、用戶權限) - github:https://github.com/wxiaoqi/ace-security - gitchina:http://git.oschina.net/geek_qi/ace-gate(服務鑑權)