登入工程:現代Web應用中的身份驗證技術

ThoughtWorks發表於2017-05-10

“登入工程”的前兩篇文章分別介紹了《傳統Web應用中的身份驗證技術》,以及《現代Web應用中的典型身份驗證需求》,接下來是時候介紹適應於現代Web應用中的身份驗證實踐了。

登入系統

首先,我們要為“登入”做一個簡要的定義,令後續的講述更準確。之前的兩篇文章有意無意地混淆了“登入”與“身份驗證”的說法,因為在本篇之前,不少“傳統Web應用”都將對身份的識別看作整個登入的過程,很少出現像企業應用環境中那樣複雜的情景和需求。但從之前的文章中我們看到,現代Web應用對身份驗證相關的需求已經向複雜化發展了。

我們有必要重新認識一下登入系統。登入指的是從識別使用者身份,到允許使用者訪問其許可權相應的資源的過程。舉個例子,在網上買好了票之後去影院觀影的過程就是一個典型的登入過程:我們先去取票機,輸入驗證碼取票;接著拿到票去影廳檢票進入。取票的過程即身份驗證,它能夠證明我們擁有這張票;而後面檢票的過程,則是授權訪問的過程。之所以要分成這兩個過程,最直接的原因還是業務形態本身具有複雜性——如果觀景過程是免費匿名的,也就免去了這些過程。

在登入的過程中,“鑑權”與“授權”是兩個最關鍵的過程。接下來要介紹的一些技術和實踐,也包含在這兩個方面中。雖然現代Web應用的登入需求比較複雜,但只要處理好了鑑權和授權兩個方面,其餘各個方面的問題也將迎刃而解。在現代Web應用的登入工程實踐中,需要結合傳統Web應用的典型實踐,以及一些新的思路,才能既解決好登入需求,又能符合Web的輕量級架構思路。

解析常見的登入場景

在簡單的Web系統中,典型的鑑權也就是要求使用者輸入並比對使用者名稱和密碼的過程,而授權則是確保會話Cookie存在。而在稍微複雜的Web系統中,則需要考慮多種鑑權方式,以及多種授權場景。上一篇文章中所述的“多種登入方式”和“雙因子鑑權”就是多種鑑權方式的例子。有經驗的人經常調侃說,只要理解了鑑權與授權,就能清晰地理解登入系統了。不光如此,這也是安全登入系統的基礎所在。

鑑權的形式豐富多彩,有傳統的使用者名稱密碼對、客戶端證書,有人們越來越熟悉的第三方登入、手機驗證,以及新興的掃碼和指紋等方式,它們都能用於對使用者的身份進行識別。在成功識別使用者之後,在使用者訪問資源或執行操作之前,我們還需要對使用者的操作進行授權。

在一些特別簡單的情形中——使用者一經識別,就可以無限制地訪問資源、執行所有操作——系統直接對所有“已登入的人”放行。比如高速公路收費站,只要車輛有合法的號牌即可放行,不需要給駕駛員發一張用於指示“允許行駛的方向或時間”的票據。除了這類特別簡單的情形之外,授權更多時候是比較複雜的工作。

在單一的傳統Web應用中,授權的過程通常由會話Cookie來完成——只要伺服器發現瀏覽器攜帶了對應的Cookie,即允許使用者訪問資源、執行操作。而在瀏覽器之外,例如在Web API呼叫、移動應用和富 Web 應用等場景中,要提供安全又不失靈活的授權方式,就需要藉助令牌技術。

令牌

令牌是一個在各種介紹登入技術的文章中常被提及的概念,也是現代Web應用系統中非常關鍵的技術。令牌是一個非常簡單的概念,它指的是在使用者通過身份驗證之後,為使用者分配的一個臨時憑證。在系統內部,各個子系統只需要以統一的方式正確識別和處理這個憑證即可完成對使用者的訪問和操作進行授權。在上文所提到的例子中,電影票就是一個典型的令牌。影廳門口的工作人員只需要確認來客手持印有對應場次的電影票即視為合法訪問,而不需要理會客戶是從何種渠道取得了電影票(比如自行購買、朋友贈予等),電影票在本場次範圍內可以持續使用(比如可以中場出去休息等)、過期作廢。通過電影票這樣一個簡單的令牌機制,電影票的出售渠道可以豐富多樣,檢票人員的工作卻仍然簡單輕鬆。

從這個例子也可以看出令牌並非什麼神奇的機制,只是一種很常見的做法。還記得第一篇文章中所述的“自包含的Cookie”嗎?那實際上就是一個令牌而已,而且在令牌中寫有關於有效性的內容——正如一個電影票上會寫明場次與影廳編號一樣。可見,在Web安全系統中引入令牌的做法,有著與傳統場合一樣的妙用。在安全系統中,令牌經常用於包含安全上下文資訊,例如被識別的使用者資訊、令牌的頒發來源、令牌本身的有效期等。另外,在必要時可以由系統廢止令牌,在它下次被使用用於訪問、操作時,使用者被禁止。

由於令牌有這些特殊的妙用,因此安全行業對令牌標準的制定工作一直沒有停止過。在現代化Web系統的演進過程中,流行的方式是選用基於Web技術的“簡單”的技術來代替相對複雜、重量級的技術。典型地,比如使用JSON-RPC或REST介面代替了SOAP格式的服務呼叫,用微服務架構代替了SOA架構等等。而適用於Web技術的令牌標準就是Json Web Token(JWT),它規範了一種基於JSON的令牌的簡單格式,可用於安全地封裝安全上下文資訊。

OAuth 2、Open ID Connect

令牌在廣為使用的OAuth技術中被採用來完成授權的過程。OAuth是一種開放的授權模型,它規定了一種供資源擁有方與消費方之間簡單又直觀的互動方法,即從消費方向資源擁有方發起使用AccessToken(訪問令牌)簽名的HTTP請求。這種方式讓消費方應用在無需(也無法)獲得使用者憑據的情況下,只要使用者完成鑑權過程並同意消費方以自己的身份呼叫資料和操作,消費方就可以獲得能夠完成功能的訪問令牌。OAuth簡單的流程和自由的程式設計模型讓它很好地滿足了開放平臺場景中授權第三方應用使用使用者資料的需求。不少網際網路公司建設開放平臺,將它們的使用者在其平臺上的資料以 API 的形式開放給第三方應用來使用,從而讓使用者享受更豐富的服務。

OAuth在各個開放平臺的成功使用,令更多開發者瞭解到它,並被它簡單明確的流程所吸引。此外,OAuth協議規定的是授權模型,並不規定訪問令牌的資料格式,也不限制在整個登入過程中需要使用的鑑權方法。人們很快發現,只要對OAuth進行合適的利用即可將其用於各種自有系統中的場景。例如,將 Web 服務視作資源擁有方,而將富Web應用或者移動應用視作消費方應用,就與開放平臺的場景完全吻合。

另一個大量實踐的場景是基於OAuth的單點登入。OAuth並沒有對鑑權的部分做規定,也不要求在握手互動過程中包含使用者的身份資訊,因此它並不適合作為單點登入系統來使用。然而,由於OAuth的流程中隱含了鑑權的步驟,因而仍然有不少開發者將這一鑑權的步驟用作單點登入系統,這也儼然衍生成為一種實踐模式。更有人將這個實踐進行了標準化,它就是Open ID Connect——基於OAuth的身份上下文協議,通過它即可以JWT的形式安全地在多個應用中共享使用者身份。接下來,只要讓鑑權伺服器支援較長的會話時間,就可以利用OAuth為多個業務系統提供單點登入功能了。

我們還沒有討論OAuth對鑑權系統的影響。實際上,OAuth對鑑權系統沒有影響,在它的框架內,只是假設已經存在了一種可用於識別使用者的有效機制,而這種機制具體是怎麼工作的,OAuth並不關心。因此我們既可以使用使用者名稱密碼(大多數開放平臺提供商都是這種方式),也可以使用掃碼登入來識別使用者,更可以提供諸如“記住密碼”,或者雙因子驗證等其他功能。

彙總

上面羅列了大量術語和解釋,那麼具體到一個典型的Web系統中,又應該如何對安全系統進行設計呢?綜合這些技術,從端到雲,從Web門戶到內部服務,本文給出如下架構方案建議:

推薦為整個應用的所有系統、子系統都部署全程的HTTPS,如果出於效能和成本考慮做不到,那麼至少要保證在使用者或裝置直接訪問的Web應用中全程使用HTTPS。

用不同的系統分別用作身份和登入,以及業務服務。當使用者登入成功之後,使用OpenID Connect向業務系統頒發JWT格式的訪問令牌和身份資訊。如果需要,登入系統可以提供多種登入方式,或者雙因子登入等增強功能。作為安全令牌服務(STS),它還負責頒發、重新整理、驗證和取消令牌的操作。在身份驗證的整個流程的每一個步驟,都使用OAuth及JWT中內建的機制來驗證資料的來源方是可信的:登入系統要確保登入請求來自受認可的業務應用,而業務在獲得令牌之後也需要驗證令牌的有效性。

在Web頁面應用中,應該申請時效較短的令牌。將獲取到的令牌向客戶端頁面中以httponly的方式寫入會話Cookie,以用於後續請求的授權;在後緒請求到達時,驗證請求中所攜帶的令牌,並延長其時效。基於JWT自包含的特性,輔以完備的簽名認證,Web 應用無需額外地維護會話狀態。

在富客戶端Web應用(單頁應用),或者移動端、客戶端應用中,可按照應用業務形態申請時效較長的令牌,或者用較短時效的令牌、配合專用的重新整理令牌使用。

在Web應用的子系統之間,呼叫其他子服務時,可靈活使用“應用程式身份”(如果該服務完全不直接對使用者提供呼叫),或者將使用者傳入的令牌直接傳遞到受呼叫的服務,以這種方式進行授權。各個業務系統可結合基於角色的訪問控制(RBAC)開發自有專用許可權系統。

作為工程師,我們不免會考慮,既然登入系統的需求可能如此複雜,而大家面臨的需求在很多時候又是如此類似,那麼有沒有什麼現成(Out of Box)的解決方案呢?自然是有的。IdentityServer是一個完整的開發框架,提供了普通登入到OAuth和Open ID Connect的完整實現;Open AM是一個開源的單點登入與訪問管理軟體平臺;而Microsoft Azure AD和AWS IAM則是公有云上的身份服務。幾乎在各個層次都有現成的方案可用。使用現成的產品和服務,能夠極大地縮減開發成本,尤其為創業團隊快速構建產品和靈活變化提供更有力的保障。

本文簡單解釋了登入過程中所涉及的基本原理,以及現代Web應用中用於身份驗證的幾種實用技術,希望為您在開發身份驗證系統時提供幫助。現代Web應用的身份驗證需求多變,應用本身的結構也比傳統的Web應用更復雜,需要架構師在明確了登入系統的基本原理的基礎之上,靈活利用各項技術的優勢,恰到好處地解決問題。

登入工程的系列文章到此就全部結束了,歡迎就文章內容提供反饋。

相關文章