登錄系統(tǒng)
首先揪利,我們要為“登錄”做一個簡要的定義竹伸,令后續(xù)的講述更準確辫樱。之前的兩篇文章有意無意地混淆了“登錄”與“身份驗證”的說法幸斥,因為在本篇之前匹摇,不少“傳統(tǒng)Web應(yīng)用”都將對身份的識別看作整個登錄的過程,很少出現(xiàn)像企業(yè)應(yīng)用環(huán)境中那樣復(fù)雜的情景和需求睡毒。但從之前的文章中我們看到来惧,現(xiàn)代Web應(yīng)用對身份驗證相關(guān)的需求已經(jīng)向復(fù)雜化發(fā)展了。
我們有必要重新認識一下登錄系統(tǒng)演顾。登錄指的是從識別用戶身份供搀,到允許用戶訪問其權(quán)限相應(yīng)的資源的過程。舉個例子钠至,在網(wǎng)上買好了票之后去影院觀影的過程就是一個典型的登錄過程:我們先去取票機葛虐,輸入驗證碼取票;接著拿到票去影廳檢票進入棉钧。取票的過程即身份驗證屿脐,它能夠證明我們擁有這張票;而后面檢票的過程宪卿,則是授權(quán)訪問的過程的诵。之所以要分成這兩個過程,最直接的原因還是業(yè)務(wù)形態(tài)本身具有復(fù)雜性——如果觀景過程是免費匿名的佑钾,也就免去了這些過程西疤。
在登錄的過程中,“鑒權(quán)”與“授權(quán)”是兩個最關(guān)鍵的過程休溶。接下來要介紹的一些技術(shù)和實踐代赁,也包含在這兩個方面中。雖然現(xiàn)代Web應(yīng)用的登錄需求比較復(fù)雜兽掰,但只要處理好了鑒權(quán)和授權(quán)兩個方面芭碍,其余各個方面的問題也將迎刃而解。在現(xiàn)代Web應(yīng)用的登錄工程實踐中孽尽,需要結(jié)合傳統(tǒng)Web應(yīng)用的典型實踐窖壕,以及一些新的思路,才能既解決好登錄需求泻云,又能符合Web的輕量級架構(gòu)思路艇拍。
解析常見的登錄場景
在簡單的Web系統(tǒng)中,典型的鑒權(quán)也就是要求用戶輸入并比對用戶名和密碼的過程宠纯,而授權(quán)則是確保會話Cookie存在卸夕。而在稍微復(fù)雜的Web系統(tǒng)中,則需要考慮多種鑒權(quán)方式婆瓜,以及多種授權(quán)場景快集。上一篇文章中所述的“多種登錄方式”和“雙因子鑒權(quán)”就是多種鑒權(quán)方式的例子贡羔。有經(jīng)驗的人經(jīng)常調(diào)侃說,只要理解了鑒權(quán)與授權(quán)个初,就能清晰地理解登錄系統(tǒng)了乖寒。不光如此,這也是安全登錄系統(tǒng)的基礎(chǔ)所在院溺。
鑒權(quán)的形式豐富多彩楣嘁,有傳統(tǒng)的用戶名密碼對、客戶端證書珍逸,有人們越來越熟悉的第三方登錄逐虚、手機驗證,以及新興的掃碼和指紋等方式谆膳,它們都能用于對用戶的身份進行識別叭爱。在成功識別用戶之后,在用戶訪問資源或執(zhí)行操作之前漱病,我們還需要對用戶的操作進行授權(quán)买雾。
在一些特別簡單的情形中——用戶一經(jīng)識別,就可以無限制地訪問資源杨帽、執(zhí)行所有操作——系統(tǒng)直接對所有“已登錄的人”放行漓穿。比如高速公路收費站,只要車輛有合法的號牌即可放行注盈,不需要給駕駛員發(fā)一張用于指示“允許行駛的方向或時間”的票據(jù)器净。除了這類特別簡單的情形之外,授權(quán)更多時候是比較復(fù)雜的工作当凡。
在單一的傳統(tǒng)Web應(yīng)用中,授權(quán)的過程通常由會話Cookie來完成——只要服務(wù)器發(fā)現(xiàn)瀏覽器攜帶了對應(yīng)的Cookie纠俭,即允許用戶訪問資源沿量、執(zhí)行操作。而在瀏覽器之外冤荆,例如在Web API調(diào)用朴则、移動應(yīng)用和富 Web 應(yīng)用等場景中,要提供安全又不失靈活的授權(quán)方式钓简,就需要借助令牌技術(shù)乌妒。
令牌
令牌是一個在各種介紹登錄技術(shù)的文章中常被提及的概念,也是現(xiàn)代Web應(yīng)用系統(tǒng)中非常關(guān)鍵的技術(shù)外邓。令牌是一個非常簡單的概念撤蚊,它指的是在用戶通過身份驗證之后,為用戶分配的一個臨時憑證损话。在系統(tǒng)內(nèi)部侦啸,各個子系統(tǒng)只需要以統(tǒng)一的方式正確識別和處理這個憑證即可完成對用戶的訪問和操作進行授權(quán)槽唾。在上文所提到的例子中,電影票就是一個典型的令牌光涂。影廳門口的工作人員只需要確認來客手持印有對應(yīng)場次的電影票即視為合法訪問庞萍,而不需要理會客戶是從何種渠道取得了電影票(比如自行購買、朋友贈予等)忘闻,電影票在本場次范圍內(nèi)可以持續(xù)使用(比如可以中場出去休息等)钝计、過期作廢。通過電影票這樣一個簡單的令牌機制齐佳,電影票的出售渠道可以豐富多樣私恬,檢票人員的工作卻仍然簡單輕松。
從這個例子也可以看出令牌并非什么神奇的機制重虑,只是一種很常見的做法践付。還記得第一篇文章中所述的“自包含的Cookie”嗎?那實際上就是一個令牌而已缺厉,而且在令牌中寫有關(guān)于有效性的內(nèi)容——正如一個電影票上會寫明場次與影廳編號一樣永高。可見提针,在Web安全系統(tǒng)中引入令牌的做法命爬,有著與傳統(tǒng)場合一樣的妙用。在安全系統(tǒng)中辐脖,令牌經(jīng)常用于包含安全上下文信息饲宛,例如被識別的用戶信息、令牌的頒發(fā)來源嗜价、令牌本身的有效期等艇抠。另外,在必要時可以由系統(tǒng)廢止令牌久锥,在它下次被使用用于訪問家淤、操作時,用戶被禁止瑟由。
由于令牌有這些特殊的妙用絮重,因此安全行業(yè)對令牌標準的制定工作一直沒有停止過。在現(xiàn)代化Web系統(tǒng)的演進過程中歹苦,流行的方式是選用基于Web技術(shù)的“簡單”的技術(shù)來代替相對復(fù)雜青伤、重量級的技術(shù)。典型地殴瘦,比如使用JSON-RPC或REST接口代替了SOAP格式的服務(wù)調(diào)用狠角,用微服務(wù)架構(gòu)代替了SOA架構(gòu)等等。而適用于Web技術(shù)的令牌標準就是Json Web Token(JWT)蚪腋,它規(guī)范了一種基于JSON的令牌的簡單格式擎厢,可用于安全地封裝安全上下文信息究流。
OAuth 2、Open ID Connect
令牌在廣為使用的OAuth技術(shù)中被采用來完成授權(quán)的過程动遭。OAuth是一種開放的授權(quán)模型芬探,它規(guī)定了一種供資源擁有方與消費方之間簡單又直觀的交互方法,即從消費方向資源擁有方發(fā)起使用AccessToken(訪問令牌)簽名的HTTP請求厘惦。這種方式讓消費方應(yīng)用在無需(也無法)獲得用戶憑據(jù)的情況下偷仿,只要用戶完成鑒權(quán)過程并同意消費方以自己的身份調(diào)用數(shù)據(jù)和操作,消費方就可以獲得能夠完成功能的訪問令牌宵蕉。OAuth簡單的流程和自由的編程模型讓它很好地滿足了開放平臺場景中授權(quán)第三方應(yīng)用使用用戶數(shù)據(jù)的需求酝静。不少互聯(lián)網(wǎng)公司建設(shè)開放平臺,將它們的用戶在其平臺上的數(shù)據(jù)以 API 的形式開放給第三方應(yīng)用來使用羡玛,從而讓用戶享受更豐富的服務(wù)别智。
OAuth在各個開放平臺的成功使用,令更多開發(fā)者了解到它稼稿,并被它簡單明確的流程所吸引薄榛。此外,OAuth協(xié)議規(guī)定的是授權(quán)模型让歼,并不規(guī)定訪問令牌的數(shù)據(jù)格式敞恋,也不限制在整個登錄過程中需要使用的鑒權(quán)方法。人們很快發(fā)現(xiàn)谋右,只要對OAuth進行合適的利用即可將其用于各種自有系統(tǒng)中的場景硬猫。例如,將 Web 服務(wù)視作資源擁有方改执,而將富Web應(yīng)用或者移動應(yīng)用視作消費方應(yīng)用啸蜜,就與開放平臺的場景完全吻合。
另一個大量實踐的場景是基于OAuth的單點登錄辈挂。OAuth并沒有對鑒權(quán)的部分做規(guī)定盔性,也不要求在握手交互過程中包含用戶的身份信息,因此它并不適合作為單點登錄系統(tǒng)來使用呢岗。然而,由于OAuth的流程中隱含了鑒權(quán)的步驟蛹尝,因而仍然有不少開發(fā)者將這一鑒權(quán)的步驟用作單點登錄系統(tǒng)后豫,這也儼然衍生成為一種實踐模式。更有人將這個實踐進行了標準化突那,它就是Open ID Connect——基于OAuth的身份上下文協(xié)議挫酿,通過它即可以JWT的形式安全地在多個應(yīng)用中共享用戶身份。接下來愕难,只要讓鑒權(quán)服務(wù)器支持較長的會話時間早龟,就可以利用OAuth為多個業(yè)務(wù)系統(tǒng)提供單點登錄功能了惫霸。
我們還沒有討論OAuth對鑒權(quán)系統(tǒng)的影響。實際上葱弟,OAuth對鑒權(quán)系統(tǒng)沒有影響壹店,在它的框架內(nèi),只是假設(shè)已經(jīng)存在了一種可用于識別用戶的有效機制芝加,而這種機制具體是怎么工作的硅卢,OAuth并不關(guān)心。因此我們既可以使用用戶名密碼(大多數(shù)開放平臺提供商都是這種方式)藏杖,也可以使用掃碼登錄來識別用戶将塑,更可以提供諸如“記住密碼”,或者雙因子驗證等其他功能蝌麸。
匯總
上面羅列了大量術(shù)語和解釋点寥,那么具體到一個典型的Web系統(tǒng)中,又應(yīng)該如何對安全系統(tǒng)進行設(shè)計呢来吩?綜合這些技術(shù)敢辩,從端到云,從Web門戶到內(nèi)部服務(wù)误褪,本文給出如下架構(gòu)方案建議:
推薦為整個應(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)可以提供多種登錄方式咒程,或者雙因子登錄等增強功能。作為安全令牌服務(wù)(STS)讼育,它還負責(zé)頒發(fā)帐姻、刷新、驗證和取消令牌的操作奶段。在身份驗證的整個流程的每一個步驟饥瓷,都使用OAuth及JWT中內(nèi)置的機制來驗證數(shù)據(jù)的來源方是可信的:登錄系統(tǒng)要確保登錄請求來自受認可的業(yè)務(wù)應(yīng)用,而業(yè)務(wù)在獲得令牌之后也需要驗證令牌的有效性痹籍。
在Web頁面應(yīng)用中呢铆,應(yīng)該申請時效較短的令牌。將獲取到的令牌向客戶端頁面中以httponly的方式寫入會話Cookie蹲缠,以用于后續(xù)請求的授權(quán)棺克;在后緒請求到達時悠垛,驗證請求中所攜帶的令牌,并延長其時效娜谊∪仿颍基于JWT自包含的特性,輔以完備的簽名認證因俐,Web 應(yīng)用無需額外地維護會話狀態(tài)拇惋。
在富客戶端Web應(yīng)用(單頁應(yīng)用),或者移動端抹剩、客戶端應(yīng)用中撑帖,可按照應(yīng)用業(yè)務(wù)形態(tài)申請時效較長的令牌,或者用較短時效的令牌澳眷、配合專用的刷新令牌使用胡嘿。
在Web應(yīng)用的子系統(tǒng)之間,調(diào)用其他子服務(wù)時钳踊,可靈活使用“應(yīng)用程序身份”(如果該服務(wù)完全不直接對用戶提供調(diào)用)衷敌,或者將用戶傳入的令牌直接傳遞到受調(diào)用的服務(wù),以這種方式進行授權(quán)拓瞪。各個業(yè)務(wù)系統(tǒng)可結(jié)合基于角色的訪問控制(RBAC)開發(fā)自有專用權(quán)限系統(tǒng)缴罗。
作為工程師,我們不免會考慮祭埂,既然登錄系統(tǒng)的需求可能如此復(fù)雜面氓,而大家面臨的需求在很多時候又是如此類似,那么有沒有什么現(xiàn)成(Out of Box)的解決方案呢蛆橡?自然是有的舌界。IdentityServer是一個完整的開發(fā)框架,提供了普通登錄到OAuth和Open ID Connect的完整實現(xiàn)泰演;Open AM是一個開源的單點登錄與訪問管理軟件平臺呻拌;而Microsoft Azure AD和AWS IAM則是公有云上的身份服務(wù)。幾乎在各個層次都有現(xiàn)成的方案可用睦焕。使用現(xiàn)成的產(chǎn)品和服務(wù)藐握,能夠極大地縮減開發(fā)成本,尤其為創(chuàng)業(yè)團隊快速構(gòu)建產(chǎn)品和靈活變化提供更有力的保障垃喊。
本文簡單解釋了登錄過程中所涉及的基本原理猾普,以及現(xiàn)代Web應(yīng)用中用于身份驗證的幾種實用技術(shù),希望為您在開發(fā)身份驗證系統(tǒng)時提供幫助〉抻現(xiàn)代Web應(yīng)用的身份驗證需求多變,應(yīng)用本身的結(jié)構(gòu)也比傳統(tǒng)的Web應(yīng)用更復(fù)雜妇蛀,需要架構(gòu)師在明確了登錄系統(tǒng)的基本原理的基礎(chǔ)之上耕突,靈活利用各項技術(shù)的優(yōu)勢笤成,恰到好處地解決問題。