服務架構:統一身份認證和授權技術解決方案

本文討論的是基於微服務架構下的身份認證和用戶授權的技術方案,從背景到微服務架構整套流程分解。

一、預備知識
本文討論基於微服務架構下的身份認證和用戶授權的技術方案,在閱讀之前,最好先熟悉並理解以下幾個知識點:

微服務架構相關概念:服務註冊、服務發現、API 網關
身份認證和用戶授權:SSO、CAS、OAuth2、JWT
文章在涉及到上述知識內容時,會附上參考鏈接。

二、背景
當企業的應用系統逐漸增多後,每個系統單獨管理各自的用戶數據容易行成信息孤島,分散的用戶管理模式阻礙了企業應用向平臺化演進。當企業的互聯網業務發展到一定規模,構建統一的標準化賬戶管理體系將是必不可少的,因爲它是企業互聯網雲平臺的重要基礎設施,能夠爲平臺帶來統一的帳號管理、身份認證、用戶授權等基礎能力,爲企業帶來諸如跨系統單點登錄、第三方授權登錄等基礎能力,爲構建開放平臺和業務生態提供了必要條件。

三、需求分析
在微服務架構下,必須對企業的平臺生態進行合理的業務劃分,每個業務板塊將自成系統,例如負責宣發的企業官網、主打文體的 B2B2C 商城、面向社區的物業服務系統等,這些系統業務比較獨立,應當獨立拆分。每個系統又可根據各自的業務模型進行切分,將業務模型和用戶需求統籌分析後建立恰當的領域模型,形成獨立的服務。

另外,企業平臺的客戶範圍比較複雜,有 2B 的業務,也有 2C 的,還有 2G(goverment)的,因此平臺級的統一身份管理必須涉及組織實體和個人實體兩類,其中組織實體包括政府機關(G)、企業單位(B)、團體組織(B)等,這類似於多租戶架構的概念,但又比傳統多租戶架構複雜。

一)統一身份管理(Unified Identity Manager)

統一身份管理(UIM)是整個平臺帳號和權限管控的基礎,由此構建的系統稱爲UIMS(Unified Identity Management System),平臺下所有系統的賬戶管理、身份認證、用戶授權、權限控制等行爲都經由 UIMS 處理,提供帳號密碼管理、基本資料管理、角色權限管理等功能。UIMS 基於『統一身份治理』的概念,可劃分爲兩級賬戶體系、基礎權限模塊和基礎信息模塊三大模塊。其中兩級賬戶體系將賬戶分爲組織實體帳號和個人實體賬戶兩大類,個人實體從屬於組織實體,也可以不從屬任何組織實體,且個人實體可同時從屬於多個組織實體;基礎權限模塊將各業務系統的資源權限進行統一管理和授權;基礎信息模塊用於描述組織實體和個人實體的基本信息,如組織實體名稱、地址、法人,個人實體姓名、電話號碼、性別等基礎信息。UIMS 提供統一的 API 與各子系統連接。

可以看到,衆多系統和衆多服務都將依賴於 UIMS 。本文僅涉及 UIMS 下的身份認證和用戶授權這兩塊,即兩級賬戶體系和基礎權限模塊,據此可以獨立出賬戶服務和鑑權服務,也可以合併成一個賬戶鑑權服務。

二)軟件即服務(SAAS)

企業提供對外的 IT 服務,有兩種部署模式:一是私有云部署,二是公有化服務。公有云服務即 SAAS,提供系統級的應用服務,包括企業服務如企業郵箱、辦公 OA、人力資源系統等,個人服務如個人郵箱、雲筆記、雲網盤等。平臺級的 SAAS 應用架構,實際上是一種多租戶架構的升級版,加大了統一身份治理的難度。而基於 UIMS 系統的兩級賬戶體系,可以很容易做到這一點。值得注意的是,有些系統僅提供個人賬戶服務,有些系統僅提供組織賬戶服務,有的則兩者都提供,必須處理好個人實體和組織實體之間的關係。

三)組織實體(Orginization Entity)

在 UIMS 中,組織機構應當是一種實體,與之對應的另一種實體是個人實體。注意實體(Entity)不是賬戶(Account),因此要設計一種用於組織實體登入受控系統的方法,這裏有兩種可選方案:一是增加組織實體賬戶,組織實體自身擁有賬戶,可直接進行認證登錄;二是將從屬於組織實體的個人賬戶作爲組織實體的登入憑證。無論何種方法,在認證和授權時,都應當向 UIMS 提供統一的標準的賬戶憑證,憑證的規格由 UIMS 定義,因此,組織實體的認證授權與個人實體的認證授權並無二致。

四)單點登錄(SSO)

企業平臺涉及衆多子系統,爲簡化各子系統的用戶管理,提升用戶體驗,因此實現 SSO 是統一身份認證的重要目標:一次登錄,全部訪問。對於企業內部應用來說,SSO 是必須的選項,例如企業 OA、HR、CRM 等內部系統;對於外部應用來說,SSO 是可選項,具體哪個應用應當加入 SSO 系統,由該業務系統決定,例如外部商城、物業系統等對外服務系統。無論何種應用是否採用 SSO,UIMS 在技術上應當具備 SSO 的能力。

五)授權登錄

隨着平臺業務的逐漸增長,依託於平臺的,和平臺依託的廠商和客戶等資源將極大的豐富平臺,因此必須構築開放的生態系統,以支撐業務的進一步發展。必須開放平臺級的授權登錄功能,以允許第三方應用接入。通過三方授權登錄,將平臺的服務各能力開發給第三方,並將第三方的服務和能力接入平臺,繁榮共生,共同發展。

六)服務間鑑權

業務系統切分出不同的服務,根據粒度粗細和業務需求不同,服務的數量和權限要求都不同。微服務架構下的身份認證和授權,可分爲兩種:

內部服務的認證和授權;
外部服務的認證和授權。
通常,內部服務處於安全的內網環境之下,例如鑑權服務、商品服務、訂單服務等,在對安全需求不高的情況下,可不執行認證過程,服務與服務之間是相互信任的。

微服務架構:統一身份認證和授權技術解決方案
微服務架構:統一身份認證和授權技術解決方案

而外部服務的認證和授權,通常由外部應用發起,通過反向代理或網關向安全邊界內的服務發起請求,因此必須執行嚴格的認證過程。無線端APP、Web端、桌面客戶端等外部應用下的各類服務,都屬於外部服務。

七)帳號登出和銷燬

與 SSO 相對應,UIMS 應該支持一次登出,全部登出,即 SSOff(Single Sign-Off,非標準術語);或者一次登出,部分登出,而是否全部登出或部分登出取決於用戶的選擇,例如用戶在 Web 端登出後,是否無線端 APP 也登出,這取決於用戶偏好,但系統應當提供這種能力。

此外,必須提供統一的銷燬功能,以支持用戶刪除其賬戶,一次銷燬,全部銷燬。

八)付費授權

雲平臺應具備付費授權機制,針對用戶賬戶和組織賬戶進行獨立授權。根據產品的商業策略,可執行靈活的付費模式:

時效限制:年付、季付、月付,不同時效費用不同;
功能限制:授權不同的功能,費用不同;
數量限制:最大組織數量限制、最大用戶數量限制,不同的數量費用不同。
四、技術方案
一)備選方案
上文基於『統一身份治理』的理念,提出了統一身份管理系統(UIMS)下關於身份認證和授權部分的主要需求。目前實現統一身份認證和授權的技術手段較多,總體可以歸納爲以下兩類:

傳統的 Cookie + Session 解決方案,有狀態會話模式;
基於令牌/票據的解決方案,無狀態交互模式。
具體有:

分佈式 Session
OAuth2.0
JWT
CAS
上述方案各有利弊:

分佈式 Session 是老牌的成熟解決方案,但因其狀態化通信的特性與微服務提倡的API導向無狀態通信相互違背,且共享式存儲存在安全隱患,因此微服務一般不太採用。

OAuth2.0 是業內成熟的授權登錄解決方案,然而 OA2.0 提供了4種授權模式,能夠適應多種場景,作爲基於令牌的安全系統,可以廣泛用於需要統一身份認證和授權的場景。

JWT(JSON Web Token)是一種簡潔的自包含的 JSON 聲明規範,因其分散存儲的特點而歸屬於客戶端授權模式,廣泛用於短期授權和單點登錄。由於 JWT 信息是經過簽名的,可以確保發送方的真實性,確保信息未經篡改和僞造。但由於其自包含的客戶端驗籤特性,令牌一經簽發,即無法撤銷,因此單純採用 JWT 作爲統一身份認證和授權方案無法滿足帳號統一登出和銷燬、帳號封禁和解除這幾種類型的需求。

在微服務架構下,身份認證和用戶授權通常分離出來成爲獨立的鑑權服務。在做技術選型時,應從以下幾點考慮:

滿足 SSO 的技術需求;
滿足簡便性和安全性的需求;
滿足開放性和擴展性的需求。
綜合考慮,推薦採用無狀態 API 模式,其中 OAuth2.0 能夠完全滿足。此外 JWT 除了不能滿足 SSOff 外,其他都能滿足,且是所有方案裏最爲簡便輕巧的一個,可通過搭配 API 網關來滿足 SSOff 特性的要求,因此 JWT + API 網關也是一個推薦的方案。

場景假設:構建基於圖像的物品識別系統(Image-Based Classification System)

爲便於理解統一認證和授權方案的細節,假定一種場景:團隊準備構建一套基於圖像的物品識別系統,允許用戶通過 H5 應用或 APP 上傳圖像,系統分析後返回識別結果;同時期望將此係統開放給社區和行業用戶以便商用;最後允許第三方應用將自身的功能接入 IBCS 以增強後者的能力。

下圖是該系統的微服務架構圖:

微服務架構圖
IBCS微服務架構圖

在微服務架構下,IBCS 分爲內外兩層,內層處於物理內網環境下,也稱爲內部服務,外層處於物理外網環境下,也稱爲外部服務,內外通過 API 網關連接。

內部服務:鑑權服務、配置服務、圖像識別服務屬於內部服務,通常內部服務之間是相互信任的,但在安全要求較高的場景下,內部服務也不能互信。
外部服務:桌面 APP、無線 APP、H5、第三方應用屬於外部服務,外部服務分爲兩種類型:一種是 IBCS 的一部分,如 APP、H5 這些前端應用;另一種是 IBCS 之外的第三方應用。兩種類型的授權方式是不一樣的,前者一般採用 OAuth2.0 的密碼模式,後者則採用客戶端模式。
下文將以物品識別系統爲例子,介紹這兩種推薦方案:

二)最佳方案: OAuth2.0

  1. OAuth2.0 的四種授權模式

授權碼模式(authorization code)
簡化模式(implicit)
密碼模式(resource owner password credentials)
客戶端模式(client credentials)
其中密碼模式常用於外部服務的鑑權,客戶端模式常用於內部服務鑑權和開放平臺應用的授權,授權碼模式常用於社會化登錄和 SSO,因此 OAuth2.0 可作爲完整的統一身份認證和授權方案。

  1. OAuth2.0 的幾種重要角色

必須注意的是,這些角色是相對的概念。

客戶端 Client:一般指第三方應用程序,例如用 QQ 登錄豆瓣網站,這裏的豆瓣網就是 Client;但在微服務體系裏,Client 通常是服務本身,如 APP 端的註冊登錄服務;
資源所有者 Resource Owner:一般指用戶,例如用 QQ 登錄豆瓣網站,這裏的所有者便是用戶;但在微服務體系裏,資源所有者是服務提供者本身;
資源服務器 Resource Server:一般指資源所有者授權存放用戶資源的服務器,例如用 QQ 登錄豆瓣網站,這裏的 QQ 就是資源服務器;但在微服務體系裏,服務提供者本身便是資源服務器;
授權服務器 Authorization Server:一般是指服務提供商的授權服務,例如用 QQ 登錄豆瓣網站,這裏的 QQ 便是授權服務器;類似地,在微服務體系裏,鑑權服務便是授權服務器。
3. IBCS 提供哪些功能

1)核心功能,以 API 形式暴露:

接口 描述 body 返回 權限
POST /image-classify 圖像識別 { 圖片內容, token } { 識別結果 } 受控接口
2)由 UIMS 提供的功能:

功能/API 描述 body 返回 權限
POST /accounts/ 註冊接口 { username, password } { sign-up-result } 非受控接口
POST /accounts/login 登錄接口 { username, password } { token } 受控接口
POST /accounts/logout 登出接口 { token } { logout-result } 受控接口
SignUp-Page 統一註冊頁面(UI) 非受控頁面
Login-Page 統一登錄頁面(UI) 非受控頁面
其中,註冊接口、SignUp-Page 和 Login-Page 頁面是非受控接口/頁面,意味着無須鑑權即可訪問。

SignUp-Page 和 Login-Page 頁面是由 UIMS 提供的統一的註冊和登錄頁面,當外部服務發起註冊或登錄請求時,有兩種作法:一是統一跳轉到 UIMS 的註冊或登錄頁面,用戶完成操作後調用 UIMS 的註冊和登錄 API 完成請求;二是在自己的註冊和登錄頁面完成操作,然後以用戶名和密碼作爲參數調用 UIMS 的註冊和登錄 API 完成請求。推薦採用第一種方法,類似於全網通行證,用戶體驗統一,不用重複開發註冊登錄頁面。

3)成爲開發者,獲取 IBCS 的能力集:

第一步:申請成爲開發者。開發者分爲個人開發者和組織開發者兩類,實名認證也分兩種類型進行。成爲開發者的前提是成爲平臺的註冊用戶;
第二步:創建應用,平臺審覈通過後,生成 AppId 和 AppSecret 給到開發者,每個應用對應一對 AppId 和 AppSecret。值得注意的是,每個 AppID 與用戶賬號是綁定的,因此每個 AppId 獲取資源和能力的權限受到該用戶賬戶權限的限制,典型的例子是對象存儲服務(OSS/OBS);
第三步:獲取 Access Token,開發者按照 OAuth2.0 的規範,採用客戶端(client_credentials)模式,利用申請到的 AppId 和 AppSecret 向 IBCS 申請 token;
第三步:使用 Access Token 與平臺進行交互,每次調用受控 API 時都攜帶此 token。
4)成爲開發者,創建第三方應用:

一般來說,應當獨立建設一個開放平臺,開發平臺作爲整個雲平臺的一個子系統,同樣依賴於 UIMS。在開放平臺上,應當提供一套完善的界面和流程,以引導用戶完成開發者認證和第三方應用接入的所有工作。此外,在前期階段,也可以採用線下申請的方式,由管理員人工審覈,在後臺手動錄入。

在開放平臺上,創建第三方應用的流程和步驟,與上一步驟『成爲開發者,獲取 IBCS 的能力集』一致。所不同的是,上個步驟是獲取 IBCS 的能力,而本步驟『創建第三方應用』,是基於開放平臺開發應用,類似於微信小程序。

5)成爲開發者,將異構系統(第三方應用)接入 IBCS:

應該允許開發者將異構系統(第三方應用)接入 IBCS,以增強 IBCS 的能力。例如,假設 IBCS 本身不具備識別特種汽車的能力,但允許接入其他開發者開發的基於圖像的特種汽車識別應用。

第三方應用接入,歸屬於開放平臺的範疇。接入的流程和步驟,與第三步驟『成爲開發者,獲取 IBCS 的能力集』一致,由開放平臺提供標準的 API,第三方按照接入規範執行。

  1. OAuth2.0 四種授權模式的應用場景

場景 描述 適用模式
用戶註冊(外部服務) 用戶在 APP 提供的註冊頁面,完成註冊請求 非受控接口,無須鑑權
用戶登錄(外部服務),返回 token 用戶在 APP 提供的登錄頁面,完成登錄請求,獲得 token 密碼模式(resource owner password credentials)
用戶註冊(UIMS) 用戶跳轉到 UIMS 的註冊頁面,完成註冊請求,註冊成功後,跳回到原服務 非受控接口,無須鑑權
用戶登錄(UIMS),返回 token 用戶跳轉到 UIMS 的登錄頁面,完成登錄操作,獲得授權碼,然後攜帶授權碼跳轉到重定向URI,再獲得 token 授權碼模式(authorization code)
外部服務的鑑權 用戶在 APP 上使用圖像識別服務,APP 調用 IBCS 的圖像識別 API 並返回結果給用戶 密碼模式(resource owner password credentials)
內部服務的鑑權 圖像識別服務向配置服務獲取配置信息 客戶端模式(client credentials),或簡單的 HTTP Basic 驗證
開發者:獲取 IBCS 能力集 客戶端模式(client credentials)
開發者:創建第三方應用 客戶端模式(client credentials)
開發者:接入第三方應用 客戶端模式(client credentials)
5. 客戶端鑑權和用戶鑑權

服務鑑權,從形式上分爲:

非受控服務/接口,無須鑑權;
客戶端鑑權(服務自身鑑權):客戶端(服務)在訪問另一個服務時,必須先表明客戶端自己的身份;
業務鑑權(用戶鑑權):用戶通過客戶端(服務)訪問某個資源時,必須驗證用戶自己的身份。
例如,用戶通過 APP 登錄 IBCS 後,訪問圖像識別服務的過程:用戶登錄後獲得 token,由 APP 攜帶此 token 向圖像識別服務發起請求,圖像識別服務首先調用鑑權服務驗證 APP 的身份(通過 ClientId 和 ClientSecret),然後再驗證用戶的身份(通過 token),如果 APP 和用戶都獲得授權,則請求通過,返回識別結果。

  1. 跨域問題

瀏覽器的同源策略給 Web 應用劃定了安全邊界,是 Web 應用安全模型的重要基礎。基於令牌的安全系統,在同源策略的約束下面臨兩個問題:

跨域請求;
SSO 登錄狀態的跨域保持。
1)CORS 方案

第一個問題,一般採用 CORS 方案,在服務端的響應頭聲明 Access-Control-Allow-Origin 參數即可解決跨域請求的問題。

2)同域 SSO 方案

第二個問題,在同域環境下,傳統方法是採用 Cookie 的方案。跨域環境下,也有幾種方案,從安全性和簡便性考慮,推薦採用這種方案:

根據業務需求將應用切分爲同域 SSO 應用和跨域 SSO 應用兩類;
將需要 SSO 狀態保持的應用歸到同域 SSO 應用中,將其他應用歸到跨域 SSO 應用中;
對於同域 SSO 應用,一般是企業內部應用,或相關性較高的應用,這些應用的域名採用相同的父級域名,繼續使用 Cookie 方案;
對於跨域 SSO 應用,不提供 SSO 狀態保持。當用戶首次打開此類應用時,由於 Cookie 無法跨域,因此服務端無法感知用戶的登錄狀態,此時用戶是處於未登錄狀態的;當用戶訪問受控頁面或點擊登錄頁面時,須重新執行登錄操作。
7. 登出和關閉賬戶

OAuth2.0 是集中式的令牌安全系統,可以通過撤銷令牌登出系統。關閉賬戶與此類似。

  1. 軟件授權

可在鑑權服務或 API 網關增加規則過濾器,將商業授權策略應用到授權規則中。

  1. 技術選型

後續會寫實踐篇,敬請期待……

三)第二方案:JWT + API 網關
JWT 是一種自包含的客戶端令牌系統技術規範,這是其與 OAuth2.0 最大的不同。除此之外,可以簡單地將 JWT 當作 OAuth2.0 密碼模式的半自動版本。在實施 JWT 方案時,大部分情況下與 OAuth2.0 基本一致,本文不重複闡述,只對幾個要點和不同之處加以說明。

  1. 搭配 API 網關實現令牌撤銷

由於 JWT 屬於自包含的客戶端令牌系統,令牌發出後無須服務器驗證,只需在客戶端驗證。客戶端驗證並解籤後將得到必要的信息,例如用戶基本信息和權限標識符。這種設計天然地存在無法撤銷令牌的問題。解決方案是在 API 網關對 JWT 進行攔截,這裏有多種方法:

令牌撤銷由 UIMS 發出,經由消息隊列、API 等手段通知到網關,網關維護一個已撤銷令牌的黑名單,對所有經過網關的 JWT 進行比對,TRUE 則拒絕轉發,並返回 401;
令牌撤銷由 UIMS 執行後,網關每次收到 JWT 請求時,查詢令牌數據庫(如 Redis),比對該令牌是否已經撤銷,如已撤銷則返回 401。
不過此方案仍然存在兩個問題:

將一定程度喪失 JWT 客戶端解籤的優勢,但相較於傳統的 Cookie + Session 方案,此方案更加輕巧,也更加符合微服務無狀態 API 的風格;
對於已發出的令牌,客戶端在下一次請求之前,服務端的令牌系統對此沒有控制能力,例如 SSOff 將無法很好地實現。
2. 客戶端鑑權和用戶鑑權

與 OAuth2.0 方案一致,客戶端同樣需要使用 ClientId 和 ClientSecret 鑑權。

  1. 公鑰和密鑰

JWT 規定採用非對稱加密算法對 Header 和 Payload 進行簽名。

1)非對稱算法

非對稱算法的重要特點是,使用密鑰加密時,必須用公鑰解密;用公鑰加密時,必須用密鑰解密。利用此特性,通常在服務端採用密鑰加密信息,然後客戶端採用公鑰解密信息。由於密鑰存儲在服務端,因此安全性高;公鑰本身可以公開,因此可以在客戶端存儲。

2)公鑰解密

JWT 經由服務端用密鑰加密後,發往客戶端,客戶端使用公鑰進行解密,便得到了 JWT 的明文。JWT 包含了豐富的信息(通常是用戶基本信息和權限標識符),只要解密成功,客戶端完全可以信任此 JWT,因此不必再依賴於服務端重複鑑權。

  1. 服務間鑑權

1)內部服務鑑權

以 IBCS 爲例,當圖像識別服務服務攜帶 JWT 向配置服務請求資源時,配置服務使用公鑰解密,只要解密成功,配置服務完全可以信任圖像識別服務,因此也不必再依賴於鑑權服務的重複鑑權。對於安全性要求不高的場景,也可以使用 HTTP Basic 驗證進行簡單鑑權。

2)外部服務鑑權

同樣,當外部的 APP 攜帶 JWT 向內網的圖像識別服務發起請求時,圖像識別服務使用公鑰解密,只要解密成功,圖像識別服務完全可以信任該 APP,有所不同的是,外部服務向內網服務發起請求,必須經過 API 網關,由網關執行規則過濾,確保 JWT 是仍處於有效狀態。

  1. 跨域問題

與 OAuth2.0 的跨域解決方案一致。

五、總結
本文給出了微服務架構下的統一身份認證和授權的設計方案,從平臺級 SAAS 模式下『統一身份治理』的概念出發,梳理了關鍵的需求點,提出了對應的解決方案。其中 OAuth2.0 是最佳解決方案,不過在實際運用中,應當遵循『合適原則』、『簡單原則』和『演化原則』三個原則,不能盲目照搬。

六、參考鏈接
SAAS,http://www.ruanyifeng.com/blog/2017/07/iaas-paas-saas.html
SSO, https://www.cnblogs.com/EzrealLiu/p/5559255.html
CAS, https://apereo.github.io/cas/
UIMS, https://mtide.net/平臺級SAAS架構的基礎-統一身份管理系統.html
說明文檔:

關於 JWT 的介紹,請參考 http://blog.leapoahead.com/2015/09/06/understanding-jwt/
關於 OAuth2.0 的介紹,請參考 http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
關於SSO的介紹,請參考 https://www.cnblogs.com/EzrealLiu/p/5559255.html
關於 SAAS 的介紹,請參考 http://www.ruanyifeng.com/blog/2017/07/iaas-paas-saas.html
關於統一身份管理系統的介紹,請參考 https://mtide.net/平臺級SAAS架構的基礎-統一身份管理系統.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章