本文最初發布于devever.net網站,經原作者授權由InfoQ中文站翻譯并分享。
現在,身份驗證協議的數量快趕上應用程序協議,結果,這個領域很容易讓人困惑。
最容易把人搞糊涂的是,很少有人注意到這樣一種事實:
存在許多不同種類的身份驗證協議,它們還試圖扮演完全不同的角色。
與往常一樣,首先請記住,身份驗證和授權是不一樣的功能。考慮到這一點,本質上存在三種不同的身份驗證協議類別:
- 客戶端到應用程序(客戶端身份驗證協議)
- 應用程序到驗證服務器(后端身份驗證協議)
- 單點登錄(客戶端到驗證服務器到多個應用程序)
客戶端到應用程序的身份驗證協議由客戶端發送給應用程序服務器進行身份驗證。這種協議完全不揭示應用程序服務器在幕后如何使用客戶端提供的信息對其進行身份驗證。
應用程序到驗證服務器的協議被應用程序服務器用來將客戶端的身份驗證委托給某個服務器,該客戶端已使用客戶端到應用程序的協議提供了信息,而驗證服務器可以更好地執行身份驗證決策。這種協議允許將身份驗證處理外包給專門的身份驗證服務器,并且無需讓身份驗證數據庫對所有應用程序服務器都開放訪問權限。
客戶端的身份驗證狀態(例如通過客戶端到應用程序的協議)通過單點登錄服務器驗證后,一臺服務器使用單點登錄協議與另一臺服務器通信。換句話說,它們被用來傳遞身份驗證決策。客戶端先前成功通過驗證服務器的身份驗證的事實,可以在該客戶端和應用程序服務器之間安全地傳輸。某些協議不需要進一步干預或需要單點登錄服務器可用,即可允許客戶端在初始登錄后對應用程序進行身份驗證,而其他協議則需要。
單點登錄協議實際上包含兩個協議:“客戶端到驗證服務器”部分和“客戶端到應用程序”部分。客戶端到驗證服務器部分可能是定制的,有時可能是非常普通的客戶端到應用程序的身份驗證協議。而客戶端到應用程序部分必須取決于SSO協議的設計。
客戶端到應用程序協議
在客戶端到應用程序驗證協議的范疇內,存在驗證框架和驗證方法。驗證框架是一種可擴展的框架,它允許實施任意多種驗證方法,并允許它在客戶端和應用程序服務器之間動態協商使用哪種驗證方法。
一些身份驗證框架已集成到特定的應用程序協議中。還有一些通用設計旨在被集成到任意多個應用協議中。這樣甚至將來出現的應用程序協議也可以利用框架中已經定義的所有身份驗證方法,以及這些方法的庫實現。
客戶端到應用程序的身份驗證框架:SASL
這類框架中可能最流行的是IETF的SASL。SASL沒有定義特定的有線編碼(這部分由應用程序負責),而是從本質上定義了身份驗證方法名稱(例如PLAIN、LOGIN、MD5等)的名稱空間,以及協商它們的過程。實際的方法特定協議已經執行,但是應用程序協議僅需要促成不透明二進制字符串序列的來回交換,直到身份驗證成功或失敗為止。
簡而言之,實現SASL的應用程序協議僅需要提供以下機制:
- 服務器將支持的方法名稱(字符串)列表發送到客戶端的一種途徑
- 客戶端發送其要使用的方法名稱的途徑
- 客戶端將不透明的二進制字符串發送到選定的SASL方法的一種途徑(可以由應用程序服務器不透明地輸入到SASL庫中)
- 服務器的SASL庫將不透明的二進制字符串發送到客戶端的一種途徑(可以不透明地反饋回客戶端的SASL庫)
- 驗證成功或失敗的一種通信途徑
如何提供這些機制取決于應用程序協議,該協議必須定義一些適當的有線協議。盡管特定的編組和狀態機是特定于應用程序協議的,但是SASL方法本身就足夠獨立于應用程序協議,因此實現各種SASL方法的通用SASL庫被廣泛采用。
一些最受歡迎的SASL方法是:
- PLAIN,以明文形式提供身份驗證用戶名和密碼(以及可選的授權用戶名,可能與身份驗證用戶名不同);
- LOGIN,棄用的方法,它是提供純文本用戶名和密碼的另一種方法;
- EXTERNAL,使客戶端完全不提供任何信息(可選的授權用戶名除外),并且是客戶端從連接上下文請求對其進行身份驗證的一種方式。例如,如果連接使用帶有客戶端證書的TLS,并且客戶端證書足以滿足身份驗證的目的,則可以使用此方法進行身份驗證;或者也能用于僅通過客戶端IP地址對其進行身份驗證的情況;
- ANONYMOUS,請求未經身份驗證的訪問;
- CRAM-MD5和DIGEST-MD5是質詢響應身份驗證方案,它們試圖避免傳輸未經加密的密碼;
- NTLM,windows NT LAN Manager身份驗證機制;
- GSSAPI,是指主要用于促成Kerberos身份驗證的API(參見下文)。
如今,人們通常會使用SASL方法(例如PLAIN或LOGIN),這些方法通過安全通道(例如TLS)以明文形式傳輸密碼。
客戶端到應用程序的身份驗證框架:HTTP
HTTP定義自己的身份驗證框架,并具有自己的方法集。可以說,HTTP避免SASL的原因在于其無狀態性和SASL不太相稱。由于HTTP設計的運行機制是讓客戶端發送單個請求塊,然后由服務器發送單個響應,因此HTTP協議不適用于SASL設想的身份驗證完成之前的來回數據交換。
此外,對于每個請求都必須重復這種交換。
服務器通過發送一個401 Authorization Required錯誤,和WWW-Authenticate標頭來請求身份驗證以訪問資源。該標頭包含:
- 所需的身份驗證方法;
- “域名稱”,提供對身份驗證域的描述;
- 必須為給定方法指定的其他參數。與SASL不同,一般來說一臺給定服務器只有一個方法(雖說HTTP RFC確實允許服務器通過發送多個WWW- Authenticate標頭來支持多個方法,每個方法一個標頭,但這種情況很少見)。然后,客戶端使用包含相同方法名稱和方法特定身份驗證數據的Authorization標頭重新發出其請求。(請注意,HTTP使用術語authorization-授權,而不是authentication-身份驗證。)
一些常見的HTTP身份驗證方法有:
- Basic(基本),以純文本形式指定用戶名和密碼;
- Digest(摘要),指定一個用戶名并以質詢-響應模式哈希密碼;
- Negotiate(協商),允許使用GSSAPI,并實質上在HTTP身份驗證內稱為SPNEGO的GSSAPI之上,重新實現了SASL風格的方法協商模式。因為它涉及來回交換,所以可能需要多個請求,直到身份驗證成功為止。Windows通常將“Negotiate/SPNEGO”用于NTLM或Kerberos身份驗證。
客戶端到應用程序的身份驗證框架:SSH
SSH還使用一組可擴展的方法定義了自己的身份驗證框架。最常用的方法有:
- keyboard-interactive(交互式鍵盤),通過任意終端提示登錄;
- public-key(公鑰),客戶端證明其握有指定私鑰;
- gssapi,通過Kerberos登錄(參見下文)。
客戶端到應用程序的身份驗證方法:策略
客戶端到應用程序的身份驗證方法通常可以分為幾個基本的類別:
- 完全遵循上下文身份驗證(例如TLS客戶端證書或IP地址身份驗證)(例如SASL EXTERNAL)。
- 以明文形式發送用戶名和密碼,其中安全性(如果有的話)由封裝的安全通道提供,并且在任何情況下,應用程序服務器最終以明文形式獲得密碼(例如SASL PLAIN;HTTP Basic;SSH keyboard- interactive)。
- 質詢-響應方案,其中服務器發出質詢隨機數,客戶端將密碼哈希或其他構造應用于隨機數和密碼來響應質詢(例如SASL CRAM-MD5)。
如今這些策略都已經過時了,首先是由于人們常結合使用TLS與純文本傳輸,其次是因為它們傾向于避免以哈希形式在服務器上存儲密碼,或者要求以與驗證方案相關的特定方式對密碼進行哈希處理。這樣的話,密碼哈希方法就會和身份驗證方法高度耦合。
- 非對稱密碼方案,其中客戶端在不傳輸私鑰的情況下證明其擁有私鑰(例如SSH public-key;TLS客戶端證書)。
- Shared-secret(共享秘密)方案,例如TLS-PSK。
- 零知識證明方案,例如SRP。這些加密方式整潔但很少使用,并且還是會將身份驗證協議與服務器上哈希密碼的方法緊密耦合。
- 單點登錄協議的客戶端到應用程序部分。
應用程序到身份驗證服務器
另一類身份驗證協議與客戶端到應用程序的身份驗證協議完全無關,而是應用程序到身份驗證服務器的協議,或稱后端協議。后端驗證協議是在應用程序服務器和驗證服務器之間使用的(而不是在要驗證的實體和對其進行驗證的實體之間做一個協議),以便驗證客戶端提供的驗證細節。
這些協議經常用于網絡訪問場景中,其中“應用程序”服務器是網絡設備,如路由器、交換機或Wi-Fi接入點。由于我們不希望網絡中的每個Wi-Fi接入點都保留身份驗證數據庫的副本,因此后端協議允許將身份驗證決策外包給一個中心化授權源。因此,后端協議必須與某種客戶端到應用程序的身份驗證協議結合使用:在客戶端和應用程序之間使用客戶端到應用程序協議,在應用程序和身份驗證服務器之間使用后端協議。
流行的后端身份驗證協議包括RADIUS及其后繼者DIAMETER,它們主要用于網絡訪問場景(例如撥號Internet身份驗證、Wi-Fi身份驗證等)。由于這些協議原本設計用于支持網絡訪問場景,它們都屬于“AAA”(同時支持身份驗證、授權、計費)協議。例如,如果需要,它們的計費功能可對撥號Internet連接進行基于時間和使用量的準確計費。
盡管LDAP不是為后端身份驗證協議設計的,但它有時也被當成身份驗證協議來用。應用程序服務器可以嘗試向LDAP服務器進行身份驗證來驗證用戶憑據。這種方法還有一個優點是,如果成功,則應用程序服務器還可以使用LDAP檢索有關用戶的信息。
應用程序到身份驗證服務器:關聯的客戶端到應用程序協議
RADIUS和DIAMETER這樣用于網絡訪問場景的后端驗證協議,傳統上設計用于和特定的客戶端到應用程序驗證協議結合使用,比如由PPP定義的那些。PPP是一個OSI第2層協議,支持通過串行線路和撥號調制解調器發起IP網絡連接。PPP定義了自己的可擴展身份驗證框架,并支持以下方法:
- PAP,以明文形式傳輸用戶名和密碼;
- CHAP,一種質詢響應方法(避免以明文形式傳輸密碼,但存在前文所述的質詢響應方法的缺點);
- MS-CHAP和MS-CHAPv2,CHAP的Microsoft變體;
- EAP,可擴展身份驗證協議,現代的首選協議。
EAP本身是一個身份驗證框架,定義了一組可擴展的身份驗證方法,這意味著與PPP一起使用時,方法協商分為兩個級別:首先要協商EAP,然后必須協商一個特定的EAP方法。人們認為EAP與其他PPP身份驗證協議不同,前者設計同時用于PPP和其他網絡訪問上下文(例如Wi-Fi身份驗證或以太網802.1x身份驗證)。(802.1x是對以太網的擴展,可以根據成功的EAP身份驗證來確定網絡訪問權限)。
EAP和SASL之間有一些相似之處,因為它們都是支持可擴展方法集的通用框架。但是,EAP定義了一個特定的有線協議,而SASL沒有定義。此外,EAP旨在支持網絡訪問應用程序,而SASL旨在支持應用程序級別的身份驗證應用程序。
但是,關于EAP的最重要的一點是,它從一開始就被設計為可被應用程序服務器不透明地經隧道傳輸。例如,假設你通過調制解調器撥入路由器,并建立PPP連接。路由器必須了解協議(例如PAP或CHAP),并且知道如何通過RADIUS或DIAMETER與后端服務器交互協議。
在現代應用程序中,例如Wi-Fi客戶端對一個WLAN接入點發送EAP,接入點只會將EAP消息作為不透明數據,然后將其在RADIUS或DIAMETER會話中通過隧道傳輸到一個網絡身份驗證服務器上,讓網絡身份驗證服務器來處理EAP消息。身份驗證服務器同樣可以返回封裝在RADIUS或DIAMETER會話中的EAP消息,Wi-Fi接入點將其解包并傳遞給客戶端。這樣,網絡設備就與所使用的身份驗證方法無關,并且不需要升級就能支持新的身份驗證方法。只有驗證服務器和客戶端需要升級。
請注意,客戶端永遠不會發送RADIUS或DIAMETER。RADIUS和DIAMETER是嚴格的后端協議。因為EAP消息始終在轉發到身份驗證服務器之前被封裝在RADIUS或DIAMETER消息中(身份驗證客戶端無法控制的進程),所以RADIUS或DIAMETER消息可以包括與EAP無關的,身份驗證服務器感興趣的客戶端信息消息本身。例如,如果客戶端正在為啟用802.1x的以太網端口發起驗證,則交換機可以包含關于客戶端連接到哪個端口的信息,并且身份驗證服務器可以預見它在這上面的決策。
單點登錄協議
現在,我們討論最復雜,最有趣的身份驗證協議:單點登錄協議。如前所述,單點登錄協議必須包括兩個部分:用于驗證客戶端到驗證服務器的協議,以及用于驗證客戶端到任意應用程序服務器的協議。前者可能是標準的客戶端到應用程序協議,也可能是定制的協議。而SSO協議的性質要求后者是SSO協議所特有的,并且是任何SSO協議的核心。
單點登錄協議:非Web
SSO協議可以大致分為Web和非Web SSO協議。最受歡迎的非Web SSO協議是Kerberos。
Kerberos允許客戶端使用定制的身份驗證協議向身份驗證服務器發起身份驗證;客戶端會收到一個票證,該票證能以密碼方式向應用程序服務器發起身份驗證,而無需與Kerberos身份驗證服務器之間進一步的通信(驗證服務器在用戶登錄后可能會關閉,并且不會立即讓所有應用程序無法訪問)。
該協議還支持客戶端來驗證服務器,以及服務器來驗證客戶端。如今,*nix和Windows Active Directory環境都使用Kerberos。對于客戶端到應用程序的身份驗證,通常不直接在身份驗證框架內將其實現為身份驗證方法。
相反,它通常是通過GSSAPI調用的,并且是主要的用法,例如SASL GSSAPI方法、HTTP Negotiate(GSSAPI)身份驗證方法和SSH GSSAPI身份驗證方法。
有趣的是,Kerberos的當前版本Kerberos 5于1993年發布,因此僅依賴對稱加密,避免了對非對稱加密的依賴。如果Kerberos是今天設計的,則它可能會使用公鑰加密,并且對中心化身份驗證服務器的依賴會稍少一些。
不幸的是,Web的極速增長看來已經侵蝕了所有非web協議(無論是身份驗證還是其他用途)的發展空間。(但Kerberos 5仍然是安全的。)
單點登錄協議:Web
對于Web SSO協議,客戶端到身份驗證服務器協議一直是標準的Web形式,也就是表單-cookies形式。客戶端到應用程序服務器的身份驗證協議卻很特殊。
通常,當應用程序服務器希望對客戶端進行身份驗證時,它將通過HTTP重定向將客戶端引向SSO身份驗證服務器。如果客戶端尚未通過中心化驗證,則會要求它進行驗證;否則,如果客戶端已經完成單點登錄,則流程將繼續進行而無需用戶干預。
在對用戶完成身份驗證之后,身份驗證服務器會通過另一個HTTP重定向將客戶端引回到應用程序服務器。返回請求包含從身份驗證服務器傳輸到應用程序服務器的身份驗證信息,以建立客戶端的憑據。該數據本身將以某種方式進行身份驗證,以防止客戶端對其修改。由于信息從身份驗證服務器到應用程序服務器的傳遞是通過客戶端進行的,因此客戶端就像是攜帶花粉的蜜蜂。在某些SSO實現中,應用程序服務器可以直接回調身份驗證服務器,以驗證它已通過客戶端接收到的信息。在其他SSO實現中,通過客戶端從身份驗證服務器傳遞到應用程序服務器的信息是加密保護的,不需要進一步驗證。
應當注意,上文不是對特定SSO協議的描述,而是對所有常用技術的概括。由于Web應用程序僅需要符合標準的Web瀏覽器,因此對在Web平臺之上實現的協議進行標準化的要求較少,于是出現了許多專有的Web SSO實現。
但一些標準還是出現了。今天流行的標準有:
- SAML2,安全性斷言標記語言第2版,一種XML的誤用,用于表達加密簽名語句,語句中包含受驗證方和驗證用途的信息,并在域之間傳遞此類語句。它很流行,受AWS for SSO支持。
- OAuth,一種基于HTTP的協議,用于促成網站之間的授權流。它側重于授權而非驗證,但是現在也經常用于驗證,尤其是與OpenID Connect擴展一起使用時。它很流行,受AWS for SSO支持。OpenID Connect擴展添加了身份驗證功能,并允許在身份驗證期間將用戶信息(例如電子郵件地址等)傳遞到網站。(請注意,OpenID Connect是一種位于OAuth之上的技術,與OpenID 2沒有任何關系。)
曾經被廣泛采用,但現在已經過時的協議包括:
- OpenID2,一種Web SSO協議,它使人們可以驗證對特定URL的控制。(請注意,這與基于OAuth構建的OpenID Connect無關,兩者適用的用例差異巨大。)
- LID,一種Web SSO協議,與OpenID 2類似,是OpenID 2的同期競爭對手,但是不太流行。
本地API
最后我們討論一些系統本地身份驗證API。這些不是協議,但與協議關系很近。
PAM
PAM(可插入身份驗證模塊)是nix領域中本地身份驗證的事實標準。它在linux上普遍用于本地身份驗證,并且在其他nix操作系統上也很流行。PAM提供了基于插件的身份驗證功能;PAM插件是動態鏈接庫,可以在運行時加載以提供任意身份驗證邏輯。使用何種PAM插件由系統配置確定,因此可以根據需要重新配置PAM。
盡管PAM具有高度可擴展性,但它被設計為支持終端交互式登錄應用程序,因此受到了限制。PAM模塊向用戶提交一系列零個或多個交互式提示(例如“Password:”),因此不能支持Kerberos那樣的SSO身份驗證方法(盡管有的PAM模塊可以提示用戶輸入Kerberos密碼并執行初始Kerberos登錄)。
雖然PAM主要是為了支持終端交互式登錄而設計的,但將PAM用作某些應用程序協議的后端(例如,用作SASL PLAIN的后端)也是可行且普遍的。但是,這要求應用程序服務器理解(或正確猜測)PAM模塊發出的線路提示的語義。例如,Dovecot IMAP服務器假定,如果PAM模塊要求輸入沒有字符回顯的行,則說明它要求輸入密碼;如果該模塊要求輸入一行啟用了字符回顯的內容,則它是在要求用戶名。因此,雖然PAM模塊可以被編寫為支持通過TOTP硬件密鑰進行身份驗證,并在終端上提示輸入六位數的值,但非終端應用程序(例如SASL應用程序)無法支持它,除非專門設計為支持這種模塊的提示。
GSSAPI
GSSAPI是另一個本地API,具有正式標準。它設計用于網絡應用程序(而不是終端交互),并且最常用于通過Kerberos SSO啟用身份驗證。實際上,盡管它是旨在擴展到任意身份驗證方案的通用API,但它幾乎只被用于Kerberos、SPNEGO和NTLM應用程序。可以通過SASL GSSAPI方法,通過任何SASL應用程序使用GSSAPI。
原文鏈接:
https://www.devever.net/~hl/auth