微服務架構的登陸認證問題


        從過去單體應用架構到分布式應用架構再到現在的微服務架構,應用的安全訪問在不斷的經受考驗。為了適應架構的變化、需求的變化,身份認證與鑒權方案也在不斷的更新變革。面對數十個甚至上百個微服務之間的調用,如何保證高效安全的身份認證?面對外部的服務訪問,該如何提供細粒度的鑒權方案?本文將會為大家闡述微服務架構下的安全認證與鑒權方案。

        傳統的單體應用場景下,應用是一個整體,一般針對所有的請求都會進行權限校驗。請求一般會通過一個權限的攔截器進行權限的校驗,在登錄時將用戶信息緩存到 session 中,后續訪問則從緩存中獲取用戶信息。在設計的時候就建立一個能適應各種系統權限管理要求的權限模型即統一用戶管理系統,如下圖

        

        而微服務架構下,一個應用會被拆分成若干個微應用,每個微應用都需要對訪問進行鑒權,每個微應用都需要明確當前訪問用戶以及其權限。尤其當訪問來源不只是瀏覽器,還包括其他服務的調用時,單體應用架構下的鑒權方式就不是特別合適了。在微服務架構下,要考慮外部應用接入的場景、用戶 - 服務的鑒權、服務 - 服務的鑒權等多種鑒權場景。

       

         基於目前的微服務架構,David Borsos 在倫敦的微服務大會上提出了四種解決方案:

         1. 單點登錄(SSO)

          這種方案意味着每個面向用戶的服務都必須與認證服務交互,這會產生大量非常瑣碎的網絡流量和重復的工作,當應用個數達到一定數量的時候,這種方案的弊端會更加明顯。

         2. 分布式 Session 方案

         分布式會話方案原理主要是將關於用戶認證的信息存儲在共享存儲中,且通常由用戶會話作為 key 來實現的簡單分布式哈希映射。當用戶訪問微服務時,用戶數據可以從共享存儲中獲取。在某些場景下,這種方案很不錯,用戶登錄狀態是不透明的。同時也是一個高可用且可擴展的解決方案。這種方案的缺點在於共享存儲需要一定保護機制,因此需要通過安全鏈接來訪問,這時解決方案的實現就通常具有相當高的復雜性了。

         3. 客戶端 Token 方案

         令牌在客戶端生成,由身份驗證服務進行簽名,並且必須包含足夠的信息,以便可以在所有微服務中建立用戶身份。令牌會附加到每個請求上,為微服務提供用戶身份驗證,這種解決方案的安全性相對較好,但身份驗證注銷是一個大問題,緩解這種情況的方法可以使用短期令牌和頻繁檢查認證服務等。對於客戶端令牌的編碼方案,Borsos 更喜歡使用 JSON Web Tokens(JWT),它足夠簡單且庫支持程度也比較好。

        4. 客戶端 Token 與 API 網關結合

        這個方案意味着所有請求都通過網關,從而有效地隱藏了微服務。 在請求時,網關將原始用戶令牌轉換為內部會話 ID 令牌。在這種情況下,注銷就不是問題,因為網關可以在注銷時撤銷用戶的令牌。

         微服務常見安全認證方案

        HTTP 基本認證

HTTP Basic Authentication(HTTP 基本認證)是 HTTP 1.0 提出的一種認證機制,這個想必大家都很熟悉了,我不再贅述。HTTP 基本認證的過程如下:

        客戶端發送 HTTP Request 給服務器。

        因為 Request 中沒有包含 Authorization header,服務器會返回一個 401 Unauthozied 給客戶端,並且在 Response 的 Header "WWW-Authenticate" 中添加信息。

        客戶端把用戶名和密碼用 BASE64 加密后,放在 Authorization Header 中發送給服務器, 認證成功。

        服務器將 Authorization Header 中的用戶名密碼取出,進行驗證, 如果驗證通過,將根據請求,發送資源給客戶端。

        基於 Session 的認證

        基於 Session 的認證應該是最常用的一種認證機制了。用戶登錄認證成功后,將用戶相關數據存儲到 Session 中,單體應用架構中,默認 Session 會存儲在應用服務器中,並且將 Session ID 返回到客戶端,存儲在瀏覽器的 Cookie 中。

        但是在分布式架構下,Session 存放於某個具體的應用服務器中自然就無法滿足使用了,簡單的可以通過 Session 復制或者 Session 粘制的方案來解決。

        Session 復制依賴於應用服務器,需要應用服務器有 Session 復制能力,不過現在大部分應用服務器如 Tomcat、JBoss、WebSphere 等都已經提供了這個能力。除此之外,Session 復制的一大缺陷在於當節點數比較多時,大量的 Session 數據復制會占用較多網絡資源。Session 粘滯是通過負載均衡器,將統一用戶的請求都分發到固定的服務器節點上,這樣就保證了對某一用戶而言,Session 數據始終是正確的。不過這種方案依賴於負載均衡器,並且只能滿足水平擴展的集群場景,無法滿足應用分割后的分布式場景。在微服務架構下,每個微服務拆分的粒度會很細,並且不只有用戶和微服務打交道,更多還有微服務間的調用。這個時候上述兩個方案都無法滿足,就要求必須要將 Session 從應用服務器中剝離出來,存放在外部進行集中管理。可以是數據庫,也可以是分布式緩存,如 Memchached、Redis 等。這正是 David Borsos 建議的第二種方案,分布式 Session 方案。

        

           基於 Token 的認證

           隨着 Restful API、微服務的興起,基於 Token 的認證現在已經越來越普遍。Token 和 Session ID 不同,並非只是一個 key。Token 一般會包含用戶的相關信息,通過驗證 Token 就可以完成身份校驗。像 Twitter、微信、QQ、GitHub 等公有服務的 API 都是基於這種方式進行認證的,一些開發框架如 OpenStack、Kubernetes 內部 API 調用也是基於 Token 的認證。基於 Token 認證的一個典型流程如下:

         

              用戶輸入登錄信息(或者調用 Token 接口,傳入用戶信息),發送到身份認證服務進行認證(身份認證服務可以和服務端在一起,也可以分離,看微服務拆分情況了)。

              身份驗證服務驗證登錄信息是否正確,返回接口(一般接口中會包含用戶基礎信息、權限范圍、有效時間等信息),客戶端存儲接口,可以存儲在 Session 或者數據庫中。

              用戶將 Token 放在 HTTP 請求頭中,發起相關 API 調用。

              被調用的微服務,驗證 Token 權限。

              服務端返回相關資源和數據。

              基於 Token 認證的好處如下:

              服務端無狀態:Token 機制在服務端不需要存儲 session 信息,因為 Token 自身包含了所有用戶的相關信息。

              性能較好,因為在驗證 Token 時不用再去訪問數據庫或者遠程服務進行權限校驗,自然可以提升不少性能。

              支持移動設備。

              支持跨程序調用,Cookie 是不允許垮域訪問的,而 Token 則不存在這個問題。

                                                                                                                                       JWT 介紹

           JSON Web Token(JWT)是為了在網絡應用環境間傳遞聲明而執行的一種基於 JSON 的開放標准(RFC 7519)。來自 JWT RFC 7519 標准化的摘要說明:JSON Web Token 是一種緊湊的,URL 安全的方式,表示要在雙方之間傳輸的聲明。JWT 一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也可以增加一些額外的其它業務邏輯所必須的聲明信息,該 Token 也可直接被用於認證,也可被加密。

              JWT 認證流程

              客戶端不需要持有密鑰,由服務端通過密鑰生成Token。

              客戶端登錄時通過賬號和密碼到服務端進行認證,認證通過后,服務端通過持有的密鑰生成Token,Token中一般包含失效時長和用戶唯一標識,如用戶ID,服務端返回Token給客戶端。

              客戶端保存服務端返回的Token。 

              客戶端進行業務請求時在Head的Authorization字段里面放置Token,如: Authorization: Bearer Token 

              服務端對請求的Token進行校驗,並通過Redis查找Token是否存在,主要是為了解決用戶注銷,但Token還在時效內的問題,如果Token在Redis中存在,則說明用戶已注銷;如果Token不存在,則校驗通過。

              服務端可以通過從Token取得的用戶唯一標識進行相關權限的校驗,並把此用戶標識賦予到請求參數中,業務可通過此用戶標識進行業務處理。

              用戶注銷時,服務端需要把還在時效內的Token保存到Redis中,並設置正確的失效時長。

              

               JWT 結構

               

             JWT 是由三段信息構成的,第一段為頭部(Header),第二段為載荷(Payload),第三段為簽名(Signature)。每一段內容都是一個 JSON 對象,將每一段 JSON 對象采用 BASE64 編碼,將編碼后的內容用. 鏈接一起就構成了 JWT 字符串。如下:

header.payload.signature

            1. 頭部(Header)

             頭部用於描述關於該 JWT 的最基本的信息,例如其類型以及簽名所用的算法等。這也可以被表示成一個 JSON 對象。

           { "typ": "JWT", "alg": "HS256" }

             在頭部指明了簽名算法是 HS256 算法。

             

            2. 載荷(payload)

            載荷就是存放有效信息的地方。有效信息包含三個部分:

                   標准中注冊的聲明、公共的聲明、私有的聲明

            標准中注冊的聲明(建議但不強制使用):

                   iss:JWT 簽發者

                   sub:JWT 所面向的用戶 

                   aud:接收 JWT 的一方

                   exp:JWT 的過期時間,這個過期時間必須要大於簽發時間

                   nbf:定義在什么時間之前,該 JWT 都是不可用的

                   iat:JWT 的簽發時間

                   jti:JWT 的唯一身份標識,主要用來作為一次性 token, 從而回避重放攻擊。

             公共的聲明 :

                   公共的聲明可以添加任何的信息,一般添加用戶的相關信息或其他業務需要的必要信息. 但不建議添加敏感信息,因為該部分在客戶端可解密。

             私有的聲明 :

                   私有聲明是提供者和消費者所共同定義的聲明,一般不建議存放敏感信息,因為 base64 是對稱解密的,意味着該部分信息可以歸類為明文信息。

            示例如下:

           { "iss": "Online JWT Builder", "iat": 1416797419, "exp": 1448333419, "aud": "www.primeton.com", }

           3. 簽名(signature)

           創建簽名需要使用 Base64 編碼后的 header 和 payload 以及一個秘鑰。將 base64 加密后的 header 和 base64 加密后的 payload 使用. 連接組成的字符串,通過 header 中聲明的加密方式進行加鹽 secret 組合加密,然后就構成了 jwt 的第三部分。

比如:HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

OAuth 2.0 介紹

 

OAuth 的官網介紹:An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications。OAuth 是一種開放的協議,為桌面程序或者基於 BS 的 web 應用提供了一種簡單的,標准的方式去訪問需要用戶授權的 API 服務。OAUTH 認證授權具有以下特點:

 

  1. 簡單:不管是 OAuth 服務提供者還是應用開發者,都很容易於理解與使用;

  2. 安全:沒有涉及到用戶密鑰等信息,更安全更靈活;

  3. 開放:任何服務提供商都可以實現 OAuth,任何軟件開發商都可以使用 OAuth;

 

OAuth 2.0 是 OAuth 協議的下一版本,但不向后兼容 OAuth 1.0,即完全廢止了 OAuth 1.0。 OAuth 2.0 關注客戶端開發者的簡易性。要么通過組織在資源擁有者和 HTTP 服務商之間的被批准的交互動作代表用戶,要么允許第三方應用代表用戶獲得訪問的權限。同時為 Web 應用,桌面應用和手機,和起居室設備提供專門的認證流程。2012 年 10 月,OAuth 2.0 協議正式發布為 RFC 6749。

OAuth 2.0 的流程如下:

(A)用戶打開客戶端以后,客戶端要求用戶給予授權。(B)用戶同意給予客戶端授權。(C)客戶端使用上一步獲得的授權,向認證服務器申請令牌。(D)認證服務器對客戶端進行認證以后,確認無誤,同意發放令牌。(E)客戶端使用令牌,向資源服務器申請獲取資源。(F)資源服務器確認令牌無誤,同意向客戶端開放資源。

四大角色

由授權流程圖中可以看到 OAuth 2.0 有四個角色:客戶端、資源擁有者、資源服務器、授權服務器。

        客戶端:客戶端是代表資源所有者對資源服務器發出訪問受保護資源請求的應用程序。

        資源擁有者:資源擁有者是對資源具有授權能力的人。

        資源服務器:資源所在的服務器。

 

授權服務器:為客戶端應用程序提供不同的 Token,可以和資源服務器在統一服務器上,也可以獨立出去。

參考鏈接:https://app.yinxiang.com/Home.action#n=a8af8c6c-49de-4b23-8642-42ee9c79be0d&ses=4&sh=2&sds=5&

                  http://nettm.iteye.com/blog/2304221

                 https://www.baidu.com/link?url=8tEEIae7Ss_3F5ZApGMruPxLz1Lxs93TRopBA2UCN-rSRM3TeU0l_M7xKbbuLEDqK9wIw2ajUK-g0HgGcGvtua&wd=&eqid=eac9f6a2000035a1000000035954c030

 

 

 

 

 

 

 

 

 

 

        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM