登錄工程:現(xiàn)代Web應(yīng)用中的身份驗(yàn)證技術(shù)
“登錄工程”的之前文章介紹了《現(xiàn)代Web應(yīng)用中的典型身份驗(yàn)證需求》,接下來是時(shí)候介紹適應(yīng)于現(xiàn)代Web應(yīng)用中的身份驗(yàn)證實(shí)踐了。
登錄系統(tǒng)
首先,我們要為“登錄”做一個(gè)簡(jiǎn)要的定義,令后續(xù)的講述更準(zhǔn)確。之前的兩篇文章有意無意地混淆了“登錄”與“身份驗(yàn)證”的說法,因?yàn)樵诒酒?,不?ldquo;傳統(tǒng)Web應(yīng)用”都將對(duì)身份的識(shí)別看作整個(gè)登錄的過程,很少出現(xiàn)像企業(yè)應(yīng)用環(huán)境中那樣復(fù)雜的情景和需求。但從之前的文章中我們看到,現(xiàn)代Web應(yīng)用對(duì)身份驗(yàn)證相關(guān)的需求已經(jīng)向復(fù)雜化發(fā)展了。我們有必要重新認(rèn)識(shí)一下登錄系統(tǒng)。
登錄指的是從識(shí)別用戶身份,到允許用戶訪問其權(quán)限相應(yīng)的資源的過程。
舉個(gè)例子,在網(wǎng)上買好了票之后去影院觀影的過程就是一個(gè)典型的登錄過程:我們先去取票機(jī),輸入驗(yàn)證碼取票;接著拿到票去影廳檢票進(jìn)入。取票的過程即身份驗(yàn)證,它能夠證明我們擁有這張票;而后面檢票的過程,則是授權(quán)訪問的過程。
之所以要分成這兩個(gè)過程,最直接的原因還是業(yè)務(wù)形態(tài)本身具有復(fù)雜性——如果觀景過程是免費(fèi)匿名的,也就免去了這些過程。
在登錄的過程中,“鑒權(quán)”與“授權(quán)”是兩個(gè)最關(guān)鍵的過程。接下來要介紹的一些技術(shù)和實(shí)踐,也包含在這兩個(gè)方面中。雖然現(xiàn)代Web應(yīng)用的登錄需求比較復(fù)雜,但只要處理好了鑒權(quán)和授權(quán)兩個(gè)方面,其余各個(gè)方面的問題也將迎刃而解。在現(xiàn)代Web應(yīng)用的登錄工程實(shí)踐中,需要結(jié)合傳統(tǒng)Web應(yīng)用的典型實(shí)踐,以及一些新的思路,才能既解決好登錄需求,又能符合Web的輕量級(jí)架構(gòu)思路。
解析常見的登錄場(chǎng)景
在簡(jiǎn)單的Web系統(tǒng)中,典型的鑒權(quán)也就是要求用戶輸入并比對(duì)用戶名和密碼的過程,而授權(quán)則是確保會(huì)話Cookie存在。而在稍微復(fù)雜的Web系統(tǒng)中,則需要考慮多種鑒權(quán)方式,以及多種授權(quán)場(chǎng)景。上一篇文章中所述的“多種登錄方式”和“雙因子鑒權(quán)”就是多種鑒權(quán)方式的例子。有經(jīng)驗(yàn)的人經(jīng)常調(diào)侃說,只要理解了鑒權(quán)與授權(quán),就能清晰地理解登錄系統(tǒng)了。不光如此,這也是安全登錄系統(tǒng)的基礎(chǔ)所在。
鑒權(quán)的形式豐富多彩,有傳統(tǒng)的用戶名密碼對(duì)、客戶端證書,有人們?cè)絹碓绞煜さ牡谌降卿洝⑹謾C(jī)驗(yàn)證,以及新興的掃碼和指紋等方式,它們都能用于對(duì)用戶的身份進(jìn)行識(shí)別。在成功識(shí)別用戶之后,在用戶訪問資源或執(zhí)行操作之前,我們還需要對(duì)用戶的操作進(jìn)行授權(quán)。
在一些特別簡(jiǎn)單的情形中——用戶一經(jīng)識(shí)別,就可以無限制地訪問資源、執(zhí)行所有操作——系統(tǒng)直接對(duì)所有“已登錄的人”放行。比如高速公路收費(fèi)站,只要車輛有合法的號(hào)牌即可放行,不需要給駕駛員發(fā)一張用于指示“允許行駛的方向或時(shí)間”的票據(jù)。除了這類特別簡(jiǎn)單的情形之外,授權(quán)更多時(shí)候是比較復(fù)雜的工作。
在單一的傳統(tǒng)Web應(yīng)用中,授權(quán)的過程通常由會(huì)話Cookie來完成——只要服務(wù)器發(fā)現(xiàn)瀏覽器攜帶了對(duì)應(yīng)的Cookie,即允許用戶訪問資源、執(zhí)行操作。而在瀏覽器之外,例如在Web API調(diào)用、移動(dòng)應(yīng)用和富 Web 應(yīng)用等場(chǎng)景中,要提供安全又不失靈活的授權(quán)方式,就需要借助令牌技術(shù)。
令牌
令牌是一個(gè)在各種介紹登錄技術(shù)的文章中常被提及的概念,也是現(xiàn)代Web應(yīng)用系統(tǒng)中非常關(guān)鍵的技術(shù)。令牌是一個(gè)非常簡(jiǎn)單的概念,它指的是在用戶通過身份驗(yàn)證之后,為用戶分配的一個(gè)臨時(shí)憑證。在系統(tǒng)內(nèi)部,各個(gè)子系統(tǒng)只需要以統(tǒng)一的方式正確識(shí)別和處理這個(gè)憑證即可完成對(duì)用戶的訪問和操作進(jìn)行授權(quán)。
在上文所提到的例子中,電影票就是一個(gè)典型的令牌。影廳門口的工作人員只需要確認(rèn)來客手持印有對(duì)應(yīng)場(chǎng)次的電影票即視為合法訪問,而不需要理會(huì)客戶是從何種渠道取得了電影票(比如自行購(gòu)買、朋友贈(zèng)予等),電影票在本場(chǎng)次范圍內(nèi)可以持續(xù)使用(比如可以中場(chǎng)出去休息等)、過期作廢。通過電影票這樣一個(gè)簡(jiǎn)單的令牌機(jī)制,電影票的出售渠道可以豐富多樣,檢票人員的工作卻仍然簡(jiǎn)單輕松。
從這個(gè)例子也可以看出令牌并非什么神奇的機(jī)制,只是一種很常見的做法。還記得第一篇文章中所述的“自包含的Cookie”嗎?那實(shí)際上就是一個(gè)令牌而已,而且在令牌中寫有關(guān)于有效性的內(nèi)容——正如一個(gè)電影票上會(huì)寫明場(chǎng)次與影廳編號(hào)一樣。
可見,在Web安全系統(tǒng)中引入令牌的做法,有著與傳統(tǒng)場(chǎng)合一樣的妙用。在安全系統(tǒng)中,令牌經(jīng)常用于包含安全上下文信息,例如被識(shí)別的用戶信息、令牌的頒發(fā)來源、令牌本身的有效期等。另外,在必要時(shí)可以由系統(tǒng)廢止令牌,在它下次被使用用于訪問、操作時(shí),用戶被禁止。
由于令牌有這些特殊的妙用,因此安全行業(yè)對(duì)令牌標(biāo)準(zhǔn)的制定工作一直沒有停止過。在現(xiàn)代化Web系統(tǒng)的演進(jìn)過程中,流行的方式是選用基于Web技術(shù)的“簡(jiǎn)單”的技術(shù)來代替相對(duì)復(fù)雜、重量級(jí)的技術(shù)。典型地,比如使用JSON-RPC或REST接口代替了SOAP格式的服務(wù)調(diào)用,用微服務(wù)架構(gòu)代替了SOA架構(gòu)等等。而適用于Web技術(shù)的令牌標(biāo)準(zhǔn)就是Json Web Token(JWT),它規(guī)范了一種基于JSON的令牌的簡(jiǎn)單格式,可用于安全地封裝安全上下文信息。
OAuth 2、Open ID Connect
令牌在廣為使用的OAuth技術(shù)中被采用來完成授權(quán)的過程。OAuth是一種開放的授權(quán)模型,它規(guī)定了一種供資源擁有方與消費(fèi)方之間簡(jiǎn)單又直觀的交互方法,即從消費(fèi)方向資源擁有方發(fā)起使用AccessToken(訪問令牌)簽名的HTTP請(qǐng)求。這種方式讓消費(fèi)方應(yīng)用在無需(也無法)獲得用戶憑據(jù)的情況下,只要用戶完成鑒權(quán)過程并同意消費(fèi)方以自己的身份調(diào)用數(shù)據(jù)和操作,消費(fèi)方就可以獲得能夠完成功能的訪問令牌。
OAuth簡(jiǎn)單的流程和自由的編程模型讓它很好地滿足了開放平臺(tái)場(chǎng)景中授權(quán)第三方應(yīng)用使用用戶數(shù)據(jù)的需求。不少互聯(lián)網(wǎng)公司建設(shè)開放平臺(tái),將它們的用戶在其平臺(tái)上的數(shù)據(jù)以 API 的形式開放給第三方應(yīng)用來使用,從而讓用戶享受更豐富的服務(wù)。
OAuth在各個(gè)開放平臺(tái)的成功使用,令更多開發(fā)者了解到它,并被它簡(jiǎn)單明確的流程所吸引。此外,OAuth協(xié)議規(guī)定的是授權(quán)模型,并不規(guī)定訪問令牌的數(shù)據(jù)格式,也不限制在整個(gè)登錄過程中需要使用的鑒權(quán)方法。人們很快發(fā)現(xiàn),只要對(duì)OAuth進(jìn)行合適的利用即可將其用于各種自有系統(tǒng)中的場(chǎng)景。例如,將Web服務(wù)視作資源擁有方,而將富Web應(yīng)用或者移動(dòng)應(yīng)用視作消費(fèi)方應(yīng)用,就與開放平臺(tái)的場(chǎng)景完全吻合。
另一個(gè)大量實(shí)踐的場(chǎng)景是基于OAuth的單點(diǎn)登錄。OAuth并沒有對(duì)鑒權(quán)的部分做規(guī)定,也不要求在握手交互過程中包含用戶的身份信息,因此它并不適合作為單點(diǎn)登錄系統(tǒng)來使用。不過,由于OAuth的流程中隱含了鑒權(quán)的步驟,因而仍然有不少開發(fā)者將這一鑒權(quán)的步驟用作單點(diǎn)登錄系統(tǒng),這也儼然衍生成為一種實(shí)踐模式。
更有人將這個(gè)實(shí)踐進(jìn)行了標(biāo)準(zhǔn)化,它就是Open ID Connect——基于OAuth的身份上下文協(xié)議,通過它即可以JWT的形式安全地在多個(gè)應(yīng)用中共享用戶身份。接下來,只要讓鑒權(quán)服務(wù)器支持較長(zhǎng)的會(huì)話時(shí)間,就可以利用OAuth為多個(gè)業(yè)務(wù)系統(tǒng)提供單點(diǎn)登錄功能了。
我們還沒有討論OAuth對(duì)鑒權(quán)系統(tǒng)的影響。實(shí)際上,OAuth對(duì)鑒權(quán)系統(tǒng)沒有影響,在它的框架內(nèi),只是假設(shè)已經(jīng)存在了一種可用于識(shí)別用戶的有效機(jī)制,而這種機(jī)制具體是怎么工作的,OAuth并不關(guān)心。因此我們既可以使用用戶名密碼(大多數(shù)開放平臺(tái)提供商都是這種方式),也可以使用掃碼登錄來識(shí)別用戶,更可以提供諸如“記住密碼”,或者雙因子驗(yàn)證等其他功能。
匯總
上面羅列了大量術(shù)語(yǔ)和解釋,那么具體到一個(gè)典型的Web系統(tǒng)中,又應(yīng)該如何對(duì)安全系統(tǒng)進(jìn)行設(shè)計(jì)呢?綜合這些技術(shù),從端到云,從Web門戶到內(nèi)部服務(wù),本文給出如下架構(gòu)方案建議:
推薦為整個(gè)應(yīng)用的所有系統(tǒng)、子系統(tǒng)都部署全程的HTTPS,如果出于性能和成本考慮做不到,那么至少要保證在用戶或設(shè)備直接訪問的Web應(yīng)用中全程使用HTTPS。
用不同的系統(tǒng)分別用作身份和登錄,以及業(yè)務(wù)服務(wù)。當(dāng)用戶登錄成功之后,使用OpenID Connect向業(yè)務(wù)系統(tǒng)頒發(fā)JWT格式的訪問令牌和身份信息。如果需要,登錄系統(tǒng)可以提供多種登錄方式,或者雙因子登錄等增強(qiáng)功能。作為安全令牌服務(wù)(STS),它還負(fù)責(zé)頒發(fā)、刷新、驗(yàn)證和取消令牌的操作。在身份驗(yàn)證的整個(gè)流程的每一個(gè)步驟,都使用OAuth及JWT中內(nèi)置的機(jī)制來驗(yàn)證數(shù)據(jù)的來源方是可信的:登錄系統(tǒng)要確保登錄請(qǐng)求來自受認(rèn)可的業(yè)務(wù)應(yīng)用,而業(yè)務(wù)在獲得令牌之后也需要驗(yàn)證令牌的有效性。
在Web頁(yè)面應(yīng)用中,應(yīng)該申請(qǐng)時(shí)效較短的令牌。將獲取到的令牌向客戶端頁(yè)面中以httponly的方式寫入會(huì)話Cookie,以用于后續(xù)請(qǐng)求的授權(quán);在后緒請(qǐng)求到達(dá)時(shí),驗(yàn)證請(qǐng)求中所攜帶的令牌,并延長(zhǎng)其時(shí)效?;贘WT自包含的特性,輔以完備的簽名認(rèn)證,Web應(yīng)用無需額外地維護(hù)會(huì)話狀態(tài)。
在富客戶端Web應(yīng)用(單頁(yè)應(yīng)用),或者移動(dòng)端、客戶端應(yīng)用中,可按照應(yīng)用業(yè)務(wù)形態(tài)申請(qǐng)時(shí)效較長(zhǎng)的令牌,或者用較短時(shí)效的令牌、配合專用的刷新令牌使用。
在Web應(yīng)用的子系統(tǒng)之間,調(diào)用其他子服務(wù)時(shí),可靈活使用“應(yīng)用程序身份”(如果該服務(wù)完全不直接對(duì)用戶提供調(diào)用),或者將用戶傳入的令牌直接傳遞到受調(diào)用的服務(wù),以這種方式進(jìn)行授權(quán)。各個(gè)業(yè)務(wù)系統(tǒng)可結(jié)合基于角色的訪問控制(RBAC)開發(fā)自有專用權(quán)限系統(tǒng)。
作為工程師,我們不免會(huì)考慮,既然登錄系統(tǒng)的需求可能如此復(fù)雜,而大家面臨的需求在很多時(shí)候又是如此類似,那么有沒有什么現(xiàn)成(Out of Box)的解決方案呢?
自然是有的。IdentityServer是一個(gè)完整的開發(fā)框架,提供了普通登錄到OAuth和Open ID Connect的完整實(shí)現(xiàn);Open AM是一個(gè)開源的單點(diǎn)登錄與訪問管理軟件平臺(tái);而Microsoft Azure AD和AWS IAM則是公有云上的身份服務(wù)。幾乎在各個(gè)層次都有現(xiàn)成的方案可用。使用現(xiàn)成的產(chǎn)品和服務(wù),能夠極大地縮減開發(fā)成本,尤其為創(chuàng)業(yè)團(tuán)隊(duì)快速構(gòu)建產(chǎn)品和靈活變化提供更有力的保障。
本文簡(jiǎn)單解釋了登錄過程中所涉及的基本原理,以及現(xiàn)代Web應(yīng)用中用于身份驗(yàn)證的幾種實(shí)用技術(shù),希望為您在開發(fā)身份驗(yàn)證系統(tǒng)時(shí)提供幫助?,F(xiàn)代Web應(yīng)用的身份驗(yàn)證需求多變,應(yīng)用本身的結(jié)構(gòu)也比傳統(tǒng)的Web應(yīng)用更復(fù)雜,需要架構(gòu)師在明確了登錄系統(tǒng)的基本原理的基礎(chǔ)之上,靈活利用各項(xiàng)技術(shù)的優(yōu)勢(shì),恰到好處地解決問題。
【本文是51CTO專欄作者“ThoughtWorks”的原創(chuàng)稿件,微信公眾號(hào):思特沃克,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】