轉(zhuǎn)載本文需注明出處:微信公眾號EAWorld著摔,違者必究缓窜。
本文目錄:
一、單體應用 VS 微服務
二谍咆、微服務常見安全認證方案
三禾锤、JWT介紹
四、OAuth 2.0 介紹
五摹察、思考總結(jié)
從單體應用架構(gòu)到分布式應用架構(gòu)再到微服務架構(gòu)恩掷,應用的安全訪問在不斷的經(jīng)受考驗。為了適應架構(gòu)的變化供嚎、需求的變化黄娘,身份認證與鑒權(quán)方案也在不斷的變革。面對數(shù)十個甚至上百個微服務之間的調(diào)用克滴,如何保證高效安全的身份認證逼争?面對外部的服務訪問,該如何提供細粒度的鑒權(quán)方案劝赔?本文將會為大家闡述微服務架構(gòu)下的安全認證與鑒權(quán)方案誓焦。
一、單體應用 VS 微服務
隨著微服務架構(gòu)的興起着帽,傳統(tǒng)的單體應用場景下的身份認證和鑒權(quán)面臨的挑戰(zhàn)越來越大杂伟。單體應用體系下,應用是一個整體仍翰,一般針對所有的請求都會進行權(quán)限校驗赫粥。請求一般會通過一個權(quán)限的攔截器進行權(quán)限的校驗,在登錄時將用戶信息緩存到 session 中歉备,后續(xù)訪問則從緩存中獲取用戶信息傅是。
而微服務架構(gòu)下,一個應用會被拆分成若干個微應用蕾羊,每個微應用都需要對訪問進行鑒權(quán)喧笔,每個微應用都需要明確當前訪問用戶以及其權(quán)限。尤其當訪問來源不只是瀏覽器龟再,還包括其他服務的調(diào)用時书闸,單體應用架構(gòu)下的鑒權(quán)方式就不是特別合適了。在為服務架構(gòu)下利凑,要考慮外部應用接入的場景浆劲、用戶 - 服務的鑒權(quán)嫌术、服務 - 服務的鑒權(quán)等多種鑒權(quán)場景。
David Borsos 在倫敦的微服務大會上提出了四種方案:
1. 單點登錄(SSO)
這種方案意味著每個面向用戶的服務都必須與認證服務交互牌借,這會產(chǎn)生大量非扯绕瑣碎的網(wǎng)絡流量和重復的工作,當動輒數(shù)十個微應用時膨报,這種方案的弊端會更加明顯磷籍。
2. 分布式 Session 方案
分布式會話方案原理主要是將關(guān)于用戶認證的信息存儲在共享存儲中,且通常由用戶會話作為 key 來實現(xiàn)的簡單分布式哈希映射现柠。當用戶訪問微服務時院领,用戶數(shù)據(jù)可以從共享存儲中獲取。在某些場景下够吩,這種方案很不錯比然,用戶登錄狀態(tài)是不透明的。同時也是一個高可用且可擴展的解決方案周循。這種方案的缺點在于共享存儲需要一定保護機制强法,因此需要通過安全鏈接來訪問,這時解決方案的實現(xiàn)就通常具有相當高的復雜性了鱼鼓。
3. 客戶端 Token 方案
令牌在客戶端生成拟烫,由身份驗證服務進行簽名,并且必須包含足夠的信息迄本,以便可以在所有微服務中建立用戶身份硕淑。令牌會附加到每個請求上,為微服務提供用戶身份驗證嘉赎,這種解決方案的安全性相對較好置媳,但身份驗證注銷是一個大問題,緩解這種情況的方法可以使用短期令牌和頻繁檢查認證服務等公条。對于客戶端令牌的編碼方案拇囊,Borsos 更喜歡使用 JSON Web Tokens(JWT),它足夠簡單且?guī)熘С殖潭纫脖容^好靶橱。
4. 客戶端 Token 與 API 網(wǎng)關(guān)結(jié)合
這個方案意味著所有請求都通過網(wǎng)關(guān)寥袭,從而有效地隱藏了微服務。 在請求時关霸,網(wǎng)關(guān)將原始用戶令牌轉(zhuǎn)換為內(nèi)部會話 ID 令牌传黄。在這種情況下,注銷就不是問題队寇,因為網(wǎng)關(guān)可以在注銷時撤銷用戶的令牌膘掰。
二、微服務常見安全認證方案
HTTP 基本認證
HTTP Basic Authentication(HTTP 基本認證)是 HTTP 1.0 提出的一種認證機制佳遣,這個想必大家都很熟悉了识埋,我不再贅述凡伊。HTTP 基本認證的過程如下:
客戶端發(fā)送 HTTP Request 給服務器。
因為 Request 中沒有包含 Authorization header窒舟,服務器會返回一個 401 Unauthozied 給客戶端系忙,并且在 Response 的 Header "WWW-Authenticate" 中添加信息。
客戶端把用戶名和密碼用 BASE64 加密后辜纲,放在 Authorization Header 中發(fā)送給服務器笨觅, 認證成功。
服務器將 Authorization Header 中的用戶名密碼取出耕腾,進行驗證, 如果驗證通
過杀糯,將根據(jù)請求扫俺,發(fā)送資源給客戶端。
基于 Session 的認證
基于 Session 的認證應該是最常用的一種認證機制了固翰。用戶登錄認證成功后狼纬,將用戶相關(guān)數(shù)據(jù)存儲到 Session 中,單體應用架構(gòu)中骂际,默認 Session 會存儲在應用服務器中疗琉,并且將 Session ID 返回到客戶端,存儲在瀏覽器的 Cookie 中歉铝。
但是在分布式架構(gòu)下盈简,Session 存放于某個具體的應用服務器中自然就無法滿足使用了,簡單的可以通過 Session 復制或者 Session 粘制的方案來解決太示。
Session 復制依賴于應用服務器柠贤,需要應用服務器有 Session 復制能力,不過現(xiàn)在大部分應用服務器如 Tomcat类缤、JBoss臼勉、WebSphere 等都已經(jīng)提供了這個能力。
除此之外餐弱,Session 復制的一大缺陷在于當節(jié)點數(shù)比較多時宴霸,大量的 Session 數(shù)據(jù)復制會占用較多網(wǎng)絡資源。Session 粘滯是通過負載均衡器膏蚓,將統(tǒng)一用戶的請求都分發(fā)到固定的服務器節(jié)點上瓢谢,這樣就保證了對某一用戶而言,Session 數(shù)據(jù)始終是正確的降允。不過這種方案依賴于負載均衡器恩闻,并且只能滿足水平擴展的集群場景,無法滿足應用分割后的分布式場景剧董。
在微服務架構(gòu)下幢尚,每個微服務拆分的粒度會很細破停,并且不只有用戶和微服務打交道,更多還有微服務間的調(diào)用尉剩。這個時候上述兩個方案都無法滿足真慢,就要求必須要將 Session 從應用服務器中剝離出來,存放在外部進行集中管理理茎『诮纾可以是數(shù)據(jù)庫,也可以是分布式緩存皂林,如 Memchached朗鸠、Redis 等。這正是 David Borsos 建議的第二種方案础倍,分布式 Session 方案烛占。
基于 Token 的認證
隨著 Restful API、微服務的興起沟启,基于 Token 的認證現(xiàn)在已經(jīng)越來越普遍忆家。Token 和 Session ID 不同,并非只是一個 key德迹。Token 一般會包含用戶的相關(guān)信息芽卿,通過驗證 Token 就可以完成身份校驗。像 Twitter胳搞、微信卸例、QQ、GitHub 等公有服務的 API 都是基于這種方式進行認證的流酬,一些開發(fā)框架如 OpenStack币厕、Kubernetes 內(nèi)部 API 調(diào)用也是基于 Token 的認證⊙刻冢基于 Token 認證的一個典型流程如下:
用戶輸入登錄信息(或者調(diào)用 Token 接口旦装,傳入用戶信息),發(fā)送到身份認證服務進行認證(身份認證服務可以和服務端在一起摊滔,也可以分離阴绢,看微服務拆分情況了)。
身份驗證服務驗證登錄信息是否正確艰躺,返回接口(一般接口中會包含用戶基礎(chǔ)信息呻袭、權(quán)限范圍、有效時間等信息)腺兴,客戶端存儲接口左电,可以存儲在 Session 或者數(shù)據(jù)庫中。
用戶將 Token 放在 HTTP 請求頭中,發(fā)起相關(guān) API 調(diào)用篓足。
被調(diào)用的微服務段誊,驗證 Token 權(quán)限。
服務端返回相關(guān)資源和數(shù)據(jù)栈拖。
基于 Token 認證的好處如下:
服務端無狀態(tài):Token 機制在服務端不需要存儲 session 信息连舍,因為 Token 自身包含了所有用戶的相關(guān)信息。
性能較好涩哟,因為在驗證 Token 時不用再去訪問數(shù)據(jù)庫或者遠程服務進行權(quán)限校驗索赏,自然可以提升不少性能。
支持移動設(shè)備贴彼。
支持跨程序調(diào)用潜腻,Cookie 是不允許垮域訪問的,而 Token 則不存在這個問題锻弓。
下面會重點介紹兩種基于 Token 的認證方案 JWT/Oauth2.0砾赔。
三、JWT介紹
JSON Web Token(JWT)是為了在網(wǎng)絡應用環(huán)境間傳遞聲明而執(zhí)行的一種基于 JSON 的開放標準(RFC 7519)青灼。來自 JWT RFC 7519 標準化的摘要說明:JSON Web Token 是一種緊湊的,URL 安全的方式妓盲,表示要在雙方之間傳輸?shù)穆暶髟硬ΑWT 一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便于從資源服務器獲取資源悯衬,也可以增加一些額外的其它業(yè)務邏輯所必須的聲明信息弹沽,該 Token 也可直接被用于認證,也可被加密筋粗。
JWT 認證流程
客戶端調(diào)用登錄接口(或者獲取 token 接口)策橘,傳入用戶名密碼。
服務端請求身份認證中心娜亿,確認用戶名密碼正確丽已。
服務端創(chuàng)建 JWT,返回給客戶端买决。
客戶端拿到 JWT沛婴,進行存儲(可以存儲在緩存中,也可以存儲在數(shù)據(jù)庫中督赤,如果是瀏覽器嘁灯,可以存儲在 Cookie 中)在后續(xù)請求中,在 HTTP 請求頭中加上 JWT躲舌。
服務端校驗 JWT丑婿,校驗通過后,返回相關(guān)資源和數(shù)據(jù)。
JWT 結(jié)構(gòu)
JWT 是由三段信息構(gòu)成的羹奉,第一段為頭部(Header)秒旋,第二段為載荷(Payload),第三段為簽名(Signature)尘奏。每一段內(nèi)容都是一個 JSON 對象滩褥,將每一段 JSON 對象采用 BASE64 編碼,將編碼后的內(nèi)容用. 鏈接一起就構(gòu)成了 JWT 字符串炫加。如下:
header.payload.signature
1. 頭部(Header)
頭部用于描述關(guān)于該 JWT 的最基本的信息瑰煎,例如其類型以及簽名所用的算法等。這也可以被表示成一個 JSON 對象俗孝。
在頭部指明了簽名算法是 HS256 算法酒甸。
2. 載荷(payload)
載荷就是存放有效信息的地方。有效信息包含三個部分:
標準中注冊的聲明
公共的聲明
私有的聲明
標準中注冊的聲明(建議但不強制使用):
iss:JWT 簽發(fā)者
sub:JWT 所面向的用戶
aud:接收 JWT 的一方
exp:JWT 的過期時間赋铝,這個過期時間必須要大于簽發(fā)時間
nbf:定義在什么時間之前插勤,該 JWT 都是不可用的
iat:JWT 的簽發(fā)時間
jti:JWT 的唯一身份標識,主要用來作為一次性 token, 從而回避重放攻擊革骨。
公共的聲明 :
公共的聲明可以添加任何的信息农尖,一般添加用戶的相關(guān)信息或其他業(yè)務需要的必要信息. 但不建議添加敏感信息,因為該部分在客戶端可解密良哲。
私有的聲明 :
私有聲明是提供者和消費者所共同定義的聲明盛卡,一般不建議存放敏感信息,因為 base64 是對稱解密的筑凫,意味著該部分信息可以歸類為明文信息滑沧。
示例如下:
3. 簽名(signature)
創(chuàng)建簽名需要使用 Base64 編碼后的 header 和 payload 以及一個秘鑰。將 base64 加密后的 header 和 base64 加密后的 payload 使用. 連接組成的字符串巍实,通過 header 中聲明的加密方式進行加鹽 secret 組合加密滓技,然后就構(gòu)成了 jwt 的第三部分。
比如:HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
JWT 的優(yōu)點:
跨語言棚潦,JSON 的格式保證了跨語言的支撐
基于 Token令漂,無狀態(tài)
占用字節(jié)小,便于傳輸
關(guān)于 Token 注銷:
Token 的注銷瓦盛,由于 Token 不存儲在服務端洗显,由客戶端存儲,當用戶注銷時原环,Token 的有效時間還沒有到挠唆,還是有效的。所以如何在用戶注銷登錄時讓 Token 注銷是一個要關(guān)注的點嘱吗。一般有如下幾種方式:
Token 存儲在 Cookie 中玄组,這樣客戶端注銷時滔驾,自然可以清空掉
注銷時,將 Token 存放到分布式緩存中俄讹,每次校驗 Token 時區(qū)檢查下該 Token 是否已注銷哆致。不過這樣也就失去了快速校驗 Token 的優(yōu)點。
-
多采用短期令牌患膛,比如令牌有效期是 20 分鐘摊阀,這樣可以一定程度上降低注銷后 Token 可用性的風險。
四踪蹬、OAuth 2.0 介紹
OAuth 的官網(wǎng)介紹:An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications胞此。OAuth 是一種開放的協(xié)議,為桌面程序或者基于 BS 的 web 應用提供了一種簡單的跃捣,標準的方式去訪問需要用戶授權(quán)的 API 服務漱牵。OAUTH 認證授權(quán)具有以下特點:
簡單:不管是 OAuth 服務提供者還是應用開發(fā)者,都很容易于理解與使用疚漆;
安全:沒有涉及到用戶密鑰等信息酣胀,更安全更靈活;
開放:任何服務提供商都可以實現(xiàn) OAuth娶聘,任何軟件開發(fā)商都可以使用 OAuth闻镶;
OAuth 2.0 是 OAuth 協(xié)議的下一版本,但不向后兼容 OAuth 1.0丸升,即完全廢止了 OAuth 1.0儒溉。 OAuth 2.0 關(guān)注客戶端開發(fā)者的簡易性。要么通過組織在資源擁有者和 HTTP 服務商之間的被批準的交互動作代表用戶发钝,要么允許第三方應用代表用戶獲得訪問的權(quán)限。同時為 Web 應用波闹,桌面應用和手機酝豪,和起居室設(shè)備提供專門的認證流程。2012 年 10 月精堕,OAuth 2.0 協(xié)議正式發(fā)布為 RFC 6749孵淘。
授權(quán)流程
OAuth 2.0 的流程如下:
(A)用戶打開客戶端以后,客戶端要求用戶給予授權(quán)歹篓。(B)用戶同意給予客戶端授權(quán)瘫证。(C)客戶端使用上一步獲得的授權(quán),向認證服務器申請令牌庄撮。(D)認證服務器對客戶端進行認證以后背捌,確認無誤,同意發(fā)放令牌洞斯。(E)客戶端使用令牌毡庆,向資源服務器申請獲取資源。(F)資源服務器確認令牌無誤,同意向客戶端開放資源么抗。
四大角色
由授權(quán)流程圖中可以看到 OAuth 2.0 有四個角色:客戶端毅否、資源擁有者、資源服務器蝇刀、授權(quán)服務器螟加。
客戶端:客戶端是代表資源所有者對資源服務器發(fā)出訪問受保護資源請求的應用程序。
資源擁有者:資源擁有者是對資源具有授權(quán)能力的人吞琐。
資源服務器:資源所在的服務器捆探。
授權(quán)服務器:為客戶端應用程序提供不同的 Token,可以和資源服務器在統(tǒng)一服務器上顽分,也可以獨立出去徐许。
客戶端的授權(quán)模式
客戶端必須得到用戶的授權(quán)(Authorization Grant),才能獲得令牌(access token)卒蘸。OAuth 2.0 定義了四種授權(quán)方式:authorizationcode雌隅、implicit、resource owner password credentials缸沃、client credentials恰起。
1. 授權(quán)碼模式(authorization code)
授權(quán)碼模式(authorization code)是功能最完整、流程最嚴密的授權(quán)模式趾牧。它的特點就是通過客戶端的后臺服務器检盼,與"服務提供商"的認證服務器進行互動。流程如下:
用戶訪問客戶端翘单,后者將前者導向認證服務器吨枉。
用戶選擇是否給予客戶端授權(quán)。
假設(shè)用戶給予授權(quán)哄芜,認證服務器將用戶導向客戶端事先指定的"重定向 URI"(redirection URI)貌亭,同時附上一個授權(quán)碼。
客戶端收到授權(quán)碼认臊,附上早先的"重定向 URI"圃庭,向認證服務器申請令牌。這一步是在客戶端的后臺的服務器上完成的失晴,對用戶不可見剧腻。
認證服務器核對了授權(quán)碼和重定向 URI,確認無誤后涂屁,向客戶端發(fā)送訪問令牌(access token)和更新令牌(refresh token)书在。
2. 簡化模式(implicit)
簡化模式(Implicit Grant Type)不通過第三方應用程序的服務器,直接在瀏覽器中向認證服務器申請令牌胯陋,跳過了"授權(quán)碼"這個步驟蕊温,因此得名袱箱。所有步驟在瀏覽器中完成,令牌對訪問者是可見的义矛,且客戶端不需要認證发笔。流程如下:
客戶端將用戶導向認證服務器。
用戶決定是否給于客戶端授權(quán)凉翻。
假設(shè)用戶給予授權(quán)了讨,認證服務器將用戶導向客戶端指定的"重定向 URI",并在 URI 的 Hash 部分包含了訪問令牌制轰。
瀏覽器向資源服務器發(fā)出請求前计,其中不包括上一步收到的 Hash 值。
資源服務器返回一個網(wǎng)頁垃杖,其中包含的代碼可以獲取 Hash 值中的令牌男杈。
瀏覽器執(zhí)行上一步獲得的腳本,提取出令牌调俘。
瀏覽器將令牌發(fā)給客戶端伶棒。
3. 密碼模式(Resource Owner Password Credentials)
密碼模式中,用戶向客戶端提供自己的用戶名和密碼彩库》粑蓿客戶端使用這些信息,向"服務商提供商"索要授權(quán)骇钦。在這種模式中宛渐,用戶必須把自己的密碼給客戶端,但是客戶端不得儲存密碼眯搭。這通常用在用戶對客戶端高度信任的情況下窥翩,比如客戶端是操作系統(tǒng)的一部分,或者由一個著名公司出品鳞仙。而認證服務器只有在其他授權(quán)模式無法執(zhí)行的情況下鳍烁,才能考慮使用這種模式。流程如下:
用戶向客戶端提供用戶名和密碼繁扎。
客戶端將用戶名和密碼發(fā)給認證服務器,向后者請求令牌糊闽。
認證服務器確認無誤后梳玫,向客戶端提供訪問令牌。
4. 客戶端模式(Client Credentials)
客戶端模式(Client Credentials Grant)指客戶端以自己的名義右犹,而不是以用戶的名義提澎,向"服務提供商"進行認證。嚴格地說念链,客戶端模式并不屬于 OAuth 框架所要解決的問題盼忌。
在這種模式中积糯,用戶直接向客戶端注冊,客戶端以自己的名義要求"服務提供商"提供服務谦纱,其實不存在授權(quán)問題看成。流程如下:
客戶端向認證服務器進行身份認證,并要求一個訪問令牌跨嘉。
認證服務器確認無誤后川慌,向客戶端提供訪問令牌。
五祠乃、思考總結(jié)
正如 David Borsos 所建議的一種方案梦重,在微服務架構(gòu)下,我們更傾向于將 Oauth 和 JWT 結(jié)合使用亮瓷,Oauth 一般用于第三方接入的場景琴拧,管理對外的權(quán)限,所以比較適合和 API 網(wǎng)關(guān)結(jié)合嘱支,針對于外部的訪問進行鑒權(quán)(當然蚓胸,底層 Token 標準采用 JWT 也是可以的)。
JWT 更加輕巧斗塘,在微服務之間進行訪問鑒權(quán)已然足夠赢织,并且可以避免在流轉(zhuǎn)過程中和身份認證服務打交道。當然馍盟,從能力實現(xiàn)角度來說于置,類似于分布式 Session 在很多場景下也是完全能滿足需求,具體怎么去選擇鑒權(quán)方案贞岭,還是要結(jié)合實際的需求來八毯。
關(guān)于作者:王海龍
現(xiàn)任普元云計算架構(gòu)師,畢業(yè)于華東師范大學瞄桨,曾參與和負責銀聯(lián)Paas云平臺項目话速、興業(yè)銀行CAP4J項目、交通銀行信用卡中心統(tǒng)一監(jiān)控平臺項目芯侥、神華災備云平臺泊交、萬達DevOps平臺等項目。
關(guān)于EAWorld
致力于軟件架構(gòu)創(chuàng)新與實踐柱查,加速企業(yè)數(shù)字化轉(zhuǎn)型廓俭,EAii(Enterprise?Architecture?Innovation?Institute)企業(yè)架構(gòu)創(chuàng)新研究院旗下官方微信公眾號。
微信號:eaworld唉工,長按二維碼關(guān)注
閱讀原文:https://mp.weixin.qq.com/s?__biz=MzI5MDEzMzg5Nw==&mid=2660395472&idx=1&sn=2a34162721f3301bfe4059ced5789dfe&chksm=f7424b36c035c22026f54342474eae91f33248e391e957b86ee72f546ee07256537577aeaf8f#rd