掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
在微服務(wù)架構(gòu)中,有一個核心的問題是處理好“集權(quán)”(中心化)和“放權(quán)”(去中心化)的關(guān)系。雖然微服務(wù)的主旋律是把數(shù)據(jù)和業(yè)務(wù)拆成小而獨立的模塊,但我們?nèi)匀恍枰粋€強(qiáng)力的中央安保體系來確?!皵?shù)據(jù)分散,權(quán)限集中”。這一篇就談?wù)勎⒎?wù)架構(gòu)中的鑒權(quán)體系。

莒縣網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站等網(wǎng)站項目制作,到程序開發(fā),運(yùn)營維護(hù)。創(chuàng)新互聯(lián)成立與2013年到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運(yùn)維經(jīng)驗,來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。
身份認(rèn)證
身份認(rèn)證(Authentication)的目的是證明“你是你(所號稱的那個人)”。
要證明這一點,你必須掌握一個只有你自己和認(rèn)證機(jī)構(gòu)才知道的機(jī)密信息。在現(xiàn)實中,這個信息可能是 DNA、指紋、虹膜這樣的生物識別特征,但由于這種特征跟人身直接綁定且又不可修改,一旦泄露,可能被持續(xù)冒用,造成不可挽回的嚴(yán)重后果,所以現(xiàn)實中較少采用這些生物識別特征作為識別之用。
如果不采用機(jī)密信息作為判斷標(biāo)準(zhǔn),就需要一個持續(xù)的、不易偽造的“證明材料”。在中國,這個證明材料就是戶口或身份證。中國對公民信息的登記相對嚴(yán)格,所以會在小孩出生的時候要求把身份信息登記到戶口之中,形成身份證明,跟隨一生。在需要證明“你是你”的時候,拿出身份證就行了。
(生物特征不可廢棄,所以我們必須把它包一層,形成證明材料和對應(yīng)的 Persona)
與生物識別特征不同的是,身份證如果丟失,從理論上說,應(yīng)該可以掛失并且讓其失效,然后辦理一張新的身份證。不過,設(shè)計我國身份證的機(jī)構(gòu)和供應(yīng)商也許沒有考慮到這個問題,或者考慮到現(xiàn)實情況太復(fù)雜,導(dǎo)致身份證無法掛失,丟失的身份證仍然具備證明效力,但這個是后話了。
為了避免身份證被冒用,在對身份認(rèn)證要求比較嚴(yán)格的場合(比如銀行),會附加一些別的檢查,比如對比照片等等。
那么,現(xiàn)在我們來對身份認(rèn)證進(jìn)行規(guī)劃。
身份認(rèn)證中的機(jī)密信息在 Web 環(huán)境中通常以用戶名和密碼的形式存在。由于 HTTP 協(xié)議沒有“狀態(tài)”的概念,所以對于 Web 服務(wù)器來說,每次請求都是全新的體驗,都必須驗明請求者的正身。要做到這一點,客戶端可以在每次請求的時候都附上用戶名和密碼(或者別的憑據(jù)),表明身份。
可是,每次都發(fā)送用戶名和密碼增加了泄露風(fēng)險,所以在第一次驗明正身(登錄)之后,服務(wù)器可以發(fā)給調(diào)用者一個“令牌”(Token)。這樣,后端的后續(xù)身份認(rèn)證,無外乎就是把令牌換成“身份”(Identity)。這個令牌實際上就是前面說的證明材料。
我們應(yīng)該盡量讓令牌不容易仿造,但是技術(shù)上無法做到完全杜絕。所以,在敏感操作的時候可能會附加一些別的驗證,比如再次輸入密碼或者用短信驗證碼做二次校驗,這也就是前面所說的附加驗證。
權(quán)限驗證
和身份認(rèn)證相比,權(quán)限驗證(Authorization)要復(fù)雜一些。
身份認(rèn)證的輸入,要么是用戶名和密碼(或別的身份憑據(jù)),要么是令牌,只需要通過一個檢查,就能輸出身份信息。而權(quán)限的驗證要檢查的是“某用戶能不能做某事情”,所以,至少需要有兩個輸入:“用戶身份”和“想要執(zhí)行的動作”。除了這兩個輸入之外,還需要有一個具體的“判斷規(guī)則”,驗證者才能根據(jù)規(guī)則,輸出“同意”或者“拒絕”。
在現(xiàn)實中,這個判斷規(guī)則有很多種可能。
在專家主導(dǎo)的醫(yī)院里面,所有人都圍繞專家的需要服務(wù),而專家則為病人服務(wù)(執(zhí)業(yè))。根據(jù)專家的需要,同時保護(hù)敏感信息,我們可能會設(shè)置更加復(fù)雜的判斷規(guī)則,比如根據(jù)時間段、服務(wù)流程階段等來判斷,或者提供一個特定的委托授權(quán)的流程用于臨時開放權(quán)限。
不管怎么變,只要有了身份、動作和規(guī)則,我們就能做判斷。當(dāng)然,如果規(guī)則要求我們核實部分?jǐn)?shù)據(jù),我們還需要這部分的數(shù)據(jù)作輸入。不過,由誰來執(zhí)行這個判斷比較合適,值得我們探討一下。
舉一個生活中的例子。
有這么一家公司,在 A 市有個辦公室,辦公室有個戴經(jīng)理。戴經(jīng)理有一天興之所至,想起來要查一下員工老王的工資。他來到了 HR 部門,找到了 HR 主管,想要調(diào)老王的工資出來看看。
HR 看了看公司規(guī)定,經(jīng)理只能看自己所轄辦公室的員工工資,然后又看了看戴經(jīng)理,是負(fù)責(zé)成都的,再看看老王,是成都員工,然后,就把老王的工資調(diào)出來給了戴經(jīng)理。戴經(jīng)理看了,然后說,再給我看看老陳的工資啊。然后 HR 調(diào)出檔案一看,老陳是北京辦公室的,就拒絕了。
又有一天,員工老王也興之所至,想要查一下戴經(jīng)理的工資。他也來到 HR 部門,找到 HR 主管,問戴經(jīng)理的工資。HR 一看,你這不是經(jīng)理啊,怎么能查別人工資呢,就直接拒絕了。
如果看這個例子,我們就會發(fā)現(xiàn),這個規(guī)則的檢查是 HR 做的。實際上,絕大部分非 IT 的業(yè)務(wù)流程中,權(quán)限的檢查都由信息的保管方來執(zhí)行。
我們當(dāng)然也可以按照這個來建模,但是稍等,再深入分析一下。
要理解最后這一點,我們可以看兩個場景。
總結(jié)就是以下幾點。
既然如此,為什么在現(xiàn)實中還是由專業(yè)人士來兼職檢查權(quán)限呢?這也許是因為對于很多公司來說,絕大部分的數(shù)據(jù)都沒有那么敏感,所以為了降低管理成本,絕大部分的數(shù)據(jù)訪問都沒有那么嚴(yán)格地用專職人員去檢查,而是由專業(yè)人士代勞。
了解了這些之后,我們就可以開始規(guī)劃了。
這樣做的好處,就是業(yè)務(wù)變得非常純粹,而權(quán)限相關(guān)的東西完全挪出業(yè)務(wù)層面,即便業(yè)務(wù)或者權(quán)限需要頻繁變化,問題也不大。
說到這里,也順便拋一個待驗證的設(shè)想:不同公司的業(yè)務(wù)邏輯總是高度雷同,差別最大(妨礙復(fù)用)的其實是公司的管理體系。我們把組織結(jié)構(gòu)和與之相關(guān)的安全權(quán)限單獨拎出來,也許可以更好地促進(jìn)業(yè)務(wù)邏輯的復(fù)用。
鑒權(quán)服務(wù)
為了提升服務(wù)的效率,我們一般會希望盡早地做完身份認(rèn)證和權(quán)限驗證。如果用戶執(zhí)行了越權(quán)操作,那我們應(yīng)該及早中止訪問并返回錯誤提示。
前面提到,權(quán)限驗證的輸入之一是用戶身份,所以身份認(rèn)證和權(quán)限驗證通常是前后腳來做。二者組合,形成鑒權(quán)服務(wù)(Auth Service)。鑒權(quán)服務(wù)負(fù)責(zé)維護(hù)令牌身份映射以及權(quán)限規(guī)則,它的輸入是“令牌”和“想執(zhí)行的動作”,輸出是“身份”和“是否允許執(zhí)行”。
幾個例子
現(xiàn)在,我們用這樣一個場景來實驗一下整個鑒權(quán)流程。
設(shè)有這么一個訂單管理系統(tǒng),其中有一個訂單查詢功能。其權(quán)限要求如下。
要對這個權(quán)限體系進(jìn)行建模,我們必須認(rèn)識到,這些操作,雖然查看的都是訂單,但是因為是不同的業(yè)務(wù)上下文,表現(xiàn)到 API 呈現(xiàn)上也會有不同。
然后,我們可以制訂如下規(guī)則。
這樣,鑒權(quán)服務(wù)就可以根據(jù)身份、動作和規(guī)則三者來判斷訪問權(quán)限了。
(圖片來自:http://t.cn/RHRujGG)
至于賣家給小二的權(quán)限分配,根據(jù)不同需要,我們可以選擇兩個方案。第一是讓賣家自己去處理這個細(xì)粒度的權(quán)限,形成自己的一套小的權(quán)限體系,這也意味著小二訪問的可能是因賣家中轉(zhuǎn)而暴露出來的新 API。第二是把這個細(xì)粒度的權(quán)限也建模到原來的權(quán)限體系里面,加入如下新的 API 和判斷規(guī)則。
小二查看訂單: /ClerkViewOrders,檢查:
我們再來看另一個場景,查看員工信息。API 的和規(guī)則的設(shè)計如下。
員工查看自己的信息:/EmployeeViewOwnProfile(所有員工均可訪問)
員工查看其他員工的信息:/EmployeeViewProfile(所有員工均可訪問)
經(jīng)理查看員工信息:/ManagerViewProfile(當(dāng)前用戶必須為 manager 角色、請求中的員工必須屬于該 manager 負(fù)責(zé)的 location)
不同的 API 返回的數(shù)據(jù)可能有差別,比如看自己的信息可以看全,看別人的只能看名字、照片和聯(lián)系方式,經(jīng)理則可以看所有人的完整信息,這由應(yīng)用邏輯決定。
(圖片來自:http://t.cn/RHRu1e3)
再來看一個醫(yī)院的。醫(yī)院有一點不同的是,病人和病歷實際上需要在多個部門之間周轉(zhuǎn),而不同的角色處在不同部門的時候,其職能和權(quán)限會有變化。比如, 有時候?qū)嵙?xí)醫(yī)生會守急診室,住院醫(yī)生不在的時候護(hù)士也需要代理執(zhí)行醫(yī)囑,職工可能會輪崗到不同部門,等等。
基于這樣一些假想場景,我們可能會有如下一些 API 和權(quán)限。
(1) 掛號處,要求用戶必須有 clerk 身份
(2) 門診部,要求用戶必須有 doctor 身份
(3) 急診室,要求用戶必須有 doctor 身份
(4) 住院部,要求用戶必須有 doctor 或者 nurse 身份
a.入院:/InPatientAdmitPatient
b.日常檢查記錄:/InPatientCreateRoutineRecord
c.創(chuàng)建醫(yī)囑:/InPatientCreateOrder
d.出院:/InPatientDismissPatient
e.查看病歷:/InPatientViewMedicalRecord
(5) 手術(shù)室,要求用戶必須有 doctor-surgeon 身份
(6) 檢查部,要求用戶必須有 technician 身份
(7) 藥房,要求用戶必須有 pharmacist 身份
上述 API 能訪問到的數(shù)據(jù)和權(quán)限主要根據(jù)部門來進(jìn)行劃分,方便輪崗。比如,醫(yī)生在門診的時候,可以查看完整的病人病歷,但輪崗到掛號處的時候,雖然也查看病歷,但就只能查看最基本的個人信息了,用于給病人補(bǔ)辦卡片之類。
功能和數(shù)據(jù)權(quán)限
從上面幾個例子看來,我們通常可以把權(quán)限的驗證分成兩個步驟:先確定職能,然后確定職能作用范圍。
比如,先確定你能看訂單,然后確定你能看哪些訂單;先確定你能看工資,然后確定你能看誰的工資。再比如,某國法律規(guī)定,當(dāng)一個案件發(fā)生在某地,警察來調(diào)查,但只有該轄區(qū)的警察有調(diào)查權(quán),跨區(qū)域的案件必須交給聯(lián)邦警察。如此等等。
既然這兩步看上去分得很清楚,那么我們不妨給它們分別取名。用戶能不能執(zhí)行某個動作,使用某個功能,是功能權(quán)限,而能不能在某個數(shù)據(jù)上執(zhí)行該功能(訪問某部分?jǐn)?shù)據(jù)),是數(shù)據(jù)權(quán)限。
促成這種拆分方式的原因可能有下面幾種。
此外,這種形式的權(quán)限管理還可以讓業(yè)務(wù)人員在不寫代碼的情況下對功能權(quán)限進(jìn)行重新分配。如果涉及數(shù)據(jù)權(quán)限,則必然會有某種形式的判斷邏輯,寫代碼也就必不可少了。
話說回來,盡管這種拆分很常見,我們?nèi)詰?yīng)該認(rèn)識到這只是人為的一種拆分。二者都是權(quán)限驗證的一部分,都是為了回答“該用戶能不能做某件事”這個問題,本質(zhì)沒變。
需要注意的是,在制定權(quán)限規(guī)則時,制訂者需要參考業(yè)務(wù)規(guī)則,但是反之則不然。業(yè)務(wù)規(guī)則可以在完全不了解權(quán)限驗證規(guī)則的情況下執(zhí)行。甚至,從理論上說,所有的業(yè)務(wù)單元都應(yīng)該可以在完全沒有權(quán)限驗證的情況下“正常裸奔”,即假設(shè)所有人可以做所有事情,但業(yè)務(wù)應(yīng)該被正常執(zhí)行,業(yè)務(wù)規(guī)則應(yīng)該被正常遵守。用語言學(xué)的詞匯來說,就是在沒有權(quán)限驗證的情況下,業(yè)務(wù)數(shù)據(jù)中也許會有語義問題(semantic problem),但是不會有句法錯誤(syntax error)。
鑒權(quán)體系回顧
我們來回顧一下這篇文章中提到的鑒權(quán)體系。
二者合稱為“鑒權(quán)”。身份認(rèn)證輸入令牌,輸出身份。權(quán)限驗證輸入身份、動作(包括動作范圍),輸出“同意”或“拒絕”。我們希望身份和權(quán)限在一個體系內(nèi)高度一致,所以,鑒權(quán)是一個半中心化的行為,權(quán)限規(guī)則在一個體系(比如組織、應(yīng)用)內(nèi)是中心化管理的。
權(quán)限的形成需要對業(yè)務(wù)知識的了解,但規(guī)則抽象出來之后,要使用它就不需要業(yè)務(wù)知識了。權(quán)限驗證的獨立,意味著我們把“權(quán)限規(guī)則”和“業(yè)務(wù)規(guī)則”拆成了兩個部分。前者擁抱變化,而后者追求穩(wěn)定;前者在意的是業(yè)務(wù)的意義,后者在意的是業(yè)務(wù)的邏輯。
為了適應(yīng)現(xiàn)有組織形態(tài)和更清晰地展示權(quán)限信息,在給權(quán)限建模的時候我們常常會把它拆分成功能和數(shù)據(jù)權(quán)限兩種。我們應(yīng)該認(rèn)識到二者都是權(quán)限驗證的一部分,都是為了回答同一個問題:這個用戶能不能做某事。
從整個分析脈絡(luò)我們可以看到,這個鑒權(quán)體系是通用的。在設(shè)計任意一個系統(tǒng)的過程中,我們都應(yīng)該注意盡量把安全相關(guān)的判斷和業(yè)務(wù)規(guī)則拆開對待,方便集中管理權(quán)限,把業(yè)務(wù)規(guī)則提純。
對于微服務(wù)架構(gòu)來說,鑒權(quán)是一個重要的節(jié)點,它和應(yīng)用場景密切結(jié)合,是安保的最后一道關(guān)口。在對權(quán)限進(jìn)行建模的時候,我們應(yīng)該尤其謹(jǐn)慎。希望這篇文章能給大家一些啟示。
【本文是專欄作者“ThoughtWorks”的原創(chuàng)稿件,微信公眾號:思特沃克,轉(zhuǎn)載請聯(lián)系原作者】

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流