從單體應用架構到分佈式應用架構再到微服務架構,應用的安全訪問在不斷地經受考驗。爲了適應架構的變化、需求的變化,身份認證與鑑權方案也在不斷地變革。面對數十個甚至上百個微服務之間的調用,如何保證高效安全的身份認證是個難題。面對外部的服務訪問,如何提供細粒度的鑑權方案也是個難題。數據庫
單體應用VS微服務跨域
隨着微服務架構的興起,傳統的單體應用場景下的身份認證和鑑權面臨的挑戰愈來愈大。瀏覽器
在單體應用體系下,應用是一個總體,通常針對全部的請求都會進行權限校驗。請求通常會經過一個權限的攔截器進行權限的校驗,在登錄時將用戶信息緩存到Session中,後續訪問則從緩存中獲取用戶信息。緩存
而在微服務架構下,一個應用會被拆分紅若干個微應用,每一個微應用都須要對訪問進行鑑權,每一個微應用都須要明確當前訪問用戶以及其權限。尤爲是當訪問來源不僅是瀏覽器,還包括其餘服務的調用時,單體應用架構下的鑑權方式就不是特別合適了。在微服務架構下,要考慮外部應用接入的場景、用戶-服務的鑑權、服務-服務的鑑權等多種鑑權場景。安全
David Borsos在倫敦的微服務大會上提出了四種方案:服務器
1.單點登錄(SSO)。這種方案意味着,每一個面向用戶的服務都必須與認證服務交互,會產生大量很是瑣碎的網絡流量和重複的工做,當動輒數十個微應用時,這種方案的弊端會更加明顯。微信
2.分佈式Session方案。分佈式會話方案的原理主要是講關於用戶認證的信息存儲在共享存儲中,且一般由用戶會話做爲key來實現的簡單分佈式哈希映射。當用戶訪問微服務時,用戶數據能夠從共享存儲中獲取。在某些場景下,這種方案很不錯,用戶登錄狀態是不透明的。同時也是一個高可用且可擴展的解決方案。這種方案的缺點在於,共享存儲須要必定的保護機制,所以須要經過安全連接來訪問,這時解決方案的實現就一般具備至關高的複雜性了。網絡
3.客戶端Token方案。令牌(Token)在客戶端生成,由身份驗證服務進行簽名,而且必須包含足夠的信息,以即可以在全部的微服務中創建用戶身份。令牌會附加到每一個請求上,爲微服務提供用戶身份驗證,這種解決方案的安全性相對較好,可是身份驗證的註銷是一個大問題,緩解這種狀況的方法可使用短時間令牌和頻繁檢查認證服務等。對於客戶端令牌的編碼方案,Borsos更喜歡使用JSON Web Tokens(JWT),它足夠簡單,且庫支持程度也比較好。架構
4.客戶端Token與API網關結合。這個方案意味着全部的請求都會經過網關,從而有效地隱藏了微服務。在請求時,網關將原始用戶令牌轉換爲內部會話ID令牌。在這種狀況下,註銷就不是問題,由於網關能夠在註銷時撤銷用戶的令牌。負載均衡
微服務常見安全認證方案
微服務常見安全認證方案主要由三種:HTTP基本認證、基於Session的認證和基於Token的認證。
HTTP基本認證(HTTP Basic Authentication)
HTTP基本認證是HTTP1.0提出的一種認證機制,過程以下:
1.客戶端發送HTTP Request給服務器。
2.由於Request中並無包含Authorization Header,服務器就會返回一個401 Unauthozied給客戶端,而且在Response的Header的【WWW-Authenticate】屬性中添加信息。
3.客戶端把用戶名和密碼用BASE64加密後,放在Authorization Header中發送給服務器,認證成功。
4.服務器將Authorization Header中的用戶名和密碼取出,進行驗證,若是驗證經過,將根據請求,發送資源給客戶端。
基於Session的認證
基於Session的認證應該是最經常使用的一種認證機制了。用戶登錄認證成功後,將用戶相關數據存儲到Session中。單體應用架構中,默認Session會存儲在應用服務器中,而且將SessionID返回到客戶端中,存儲到瀏覽器的Cookie中;分佈式架構中,Session存放於某個具體的應用服務器天然是沒法知足使用,簡單的能夠經過Session複製或Session粘滯的方案來解決。
Session複製依賴於應用服務器,須要應用服務器有Session複製能力,不過如今大部分應用服務器如Tomcat、JBoss和WebSphere等都提供了這個能力。
除此以外,Session複製的一大缺陷在於,當節點數比較多時,大量的Session數據複製會佔用較多的網絡資源。Session粘滯是經過負載均衡器,將統一用戶的請求都分發到固定的服務器節點上,這樣就保證了對某一個用戶而言,Session數據始終是正確的。不過這種方案依賴於負載均衡器,而且只能知足水平擴展的集羣場景,沒法知足應用分割後的分佈式場景。
在微服務架構下,每一個微服務拆分的粒度會很細,而且不僅有用戶和微服務打交道,更多的還有微服務之間的調用。這個時候,上述兩個方案都沒法知足,就要求必需要將Session從應用服務器中剝離出來,存放在外部進行集中管理。能夠是數據庫,也能夠是分佈式緩存,好比Memchached、Redis等。這正是David Boros建議的第二種方案:分佈式Session方案。
基於Token的認證
隨着Restful API、微服務的興起,基於Token的認證如今已經愈來愈廣泛。Token和SessionID不一樣,並不是只是一個key。Token通常會包含用戶的相關信息,經過驗證Token就能夠完成身份校驗。像Twitter、微信、QQ、Github等公有服務的API都是基於這種方式進行認證的,一些開發框架如OpenStack、Kubernates內部API調用也是基於Token認證。基於Token認證的一個典型流程以下:
1.用戶輸入登錄信息(或者調用Token接口,傳入用戶信息),發送到身份認證服務進行認證(身份認證服務能夠和服務端在一塊兒,也能夠分離,看微服務拆分狀況)。
2.身份認證服務驗證登錄信息是否正確,返回Token(通常Token中會包含用戶基礎信息、權限範圍、有效時間等信息),客戶端存儲Token,能夠存儲在Session或者數據庫中。
3.用戶將Token放在HTTP請求頭中,發起相關API調用。
4.被調用的微服務,驗證Token權限。
5.服務端返回相關資源和數據。
基於Token認證的好處
1.服務端無狀態。Token機制在服務端不須要存儲Session信息,由於Token自身包含了全部用戶的相關信息。
2.性能較好。由於在驗證Token的時候不用再去訪問數據庫或者遠程服務進行權限校驗,天然能夠提高很多性能。
3.支持移動設備。
4.支持跨程序調用。Cookie是不容許跨域訪問的,而Token則不會存在這個問題。
轉自:https://mp.weixin.qq.com/s/x0CZpovseOuofTA_lw0HvA
"我歷來沒有被誰捧在手內心真正地愛過,每一次我都好像在剋制本身,不要發脾氣,要懂事,但是隻有我本身知道,我有多麼難過,多麼心累。"