權(quán)限管理(RBAC新解)

轉(zhuǎn)自:http://www.thinksaas.cn/group/topic/150841/
原文地址:http://www.katasoft.com/blog/2011/05/09/new-rbac-resource-based-access-control

本文討論以角色概念進(jìn)行的權(quán)限管理策略及主要以基于角色的機(jī)制進(jìn)行權(quán)限管理是遠(yuǎn)遠(yuǎn)不夠的。同時(shí)我將討論一種我認(rèn)為更好的權(quán)限管理方式。

什么是角色

當(dāng)說(shuō)到程序的權(quán)限管理時(shí),人們往往想到角色這一概念。角色是代表一系列可執(zhí)行的操作或責(zé)任的實(shí)體,用于限定你在軟件系統(tǒng)中能做什么、不能做什么。用戶(hù)帳號(hào)往往與角色相關(guān)聯(lián),因此,一個(gè)用戶(hù)在軟件系統(tǒng)中能做什么取決于與之關(guān)聯(lián)的各個(gè)角色。

例如,一個(gè)用戶(hù)以關(guān)聯(lián)了”項(xiàng)目管理員”角色的帳號(hào)登錄系統(tǒng),那這個(gè)用戶(hù)就可以做項(xiàng)目管理員能做的所有事情――如列出項(xiàng)目中的應(yīng)用、管理項(xiàng)目組成員、產(chǎn)生項(xiàng)目報(bào)表等。
從這個(gè)意義上來(lái)說(shuō),角色更多的是一種行為的概念:它表示用戶(hù)能在系統(tǒng)中進(jìn)行的操作。

基于角色的訪(fǎng)問(wèn)控制(Role-Based Access Control)

既然角色代表了可執(zhí)行的操作這一概念,一個(gè)合乎邏輯的做法是在軟件開(kāi)發(fā)中使用角色來(lái)控制對(duì)軟件功能和數(shù)據(jù)的訪(fǎng)問(wèn)。你可能已經(jīng)猜到,這種權(quán)限控制方法就叫基于角色的訪(fǎng)問(wèn)控制(Role-Based Access Control),或簡(jiǎn)稱(chēng)為RBAC。

有兩種正在實(shí)踐中使用的RBAC訪(fǎng)問(wèn)控制方式:隱式(模糊)的方式和顯示(明確)的方式。
今天依舊有大量的軟件應(yīng)用是使用隱式的訪(fǎng)問(wèn)控制方式。但我肯定的說(shuō),顯示的訪(fǎng)問(wèn)控制方式更適合于當(dāng)前的軟件應(yīng)用。

隱式的訪(fǎng)問(wèn)控制

前面提到,角色代表一系列的可執(zhí)行的操作。但我們?nèi)绾沃酪粋€(gè)角色到底關(guān)聯(lián)了哪些可執(zhí)行的操作呢?

答案是:目前的大多數(shù)應(yīng)用,你并能不明確的知道一個(gè)角色到底關(guān)聯(lián)了哪些可執(zhí)行操作。可能你心里是清楚的(你知道一個(gè)有”管理員”角色的用戶(hù)可以鎖定用戶(hù)帳號(hào)、進(jìn)行系統(tǒng)配置;一個(gè)關(guān)聯(lián)了”消費(fèi)者”這一角色的用戶(hù)可在網(wǎng)站上進(jìn)行商品選購(gòu)),但這些系統(tǒng)并沒(méi)有明確定義一個(gè)角色到底包含了哪些可執(zhí)行的行為。

拿”項(xiàng)目管理員”來(lái)說(shuō),系統(tǒng)中并沒(méi)有對(duì)”項(xiàng)目管理員”能進(jìn)行什么樣的操作進(jìn)行明確定義,它僅是一個(gè)字符串名詞。開(kāi)發(fā)人員通常將這個(gè)名詞寫(xiě)在程序里以進(jìn)行訪(fǎng)問(wèn)控制。例如,判斷一個(gè)用戶(hù)是否能查看項(xiàng)目報(bào)表,程序員可能會(huì)編碼如下:

代碼塊1. 隱式地基于角色的權(quán)限控制:

if (user.hasRole("Project Manager")){
    //show the project report button
} else {
    //don't show the button
}

在上面的示例代表中,開(kāi)發(fā)人員判斷用戶(hù)是否有”項(xiàng)目管理員”角色來(lái)決定是否顯示查看項(xiàng)目報(bào)表按鈕。請(qǐng)注意上面的代碼,它并沒(méi)有明確語(yǔ)句來(lái)定義”項(xiàng)目管理員”這一角色到底包含哪些可執(zhí)行的行為,它只是假設(shè)一個(gè)關(guān)聯(lián)了項(xiàng)目管理員角色的用戶(hù)可查看項(xiàng)目報(bào)表,而開(kāi)發(fā)人員也是基于這一假設(shè)來(lái)寫(xiě) if/else 語(yǔ)句。

脆弱的權(quán)限策略

像上面的權(quán)限訪(fǎng)問(wèn)控制是非常脆弱的。一個(gè)極小的權(quán)限方面的需求的變動(dòng)都可能導(dǎo)致上面的代碼需要重新修改。

舉例來(lái)說(shuō),假如某一天這個(gè)開(kāi)發(fā)團(tuán)隊(duì)被告知:“哦,順便說(shuō)一下,我們需要一個(gè)’部門(mén)管理員’角色,他們也可以查看項(xiàng)目報(bào)表。請(qǐng)做到這一點(diǎn)。”

這種情況下,開(kāi)發(fā)人員需要找到上面的代碼塊并將其修改為:

代碼塊2. 修改過(guò)的隱式的基于角色的權(quán)限控制:

if (user.hasRole("Project Manager") || user.hasRole("Department Manager")) {
    //show the project report button
} else {
    //don't show the button
}

隨后,開(kāi)發(fā)人員需要更新他的測(cè)試用例、重新編譯系統(tǒng),還可能需要重走軟件質(zhì)量控制(QA)流程,然后再重新部署上線(xiàn)。這一切僅僅是因?yàn)橐粋€(gè)微小的權(quán)限方面的需求變動(dòng)!

后面如果需求方又回來(lái)告訴你說(shuō)我們又有另一個(gè)角色可查看報(bào)表,或是前面關(guān)于”部門(mén)管理員可查看報(bào)表”的需求不再需要了,豈不把人累死了。

如果需求方要求動(dòng)態(tài)地創(chuàng)建、刪除角色以便他們自己配置角色,又該如何應(yīng)對(duì)呢?

像上面的情況,這種隱式的(靜態(tài)字符串)形式的基于角色的訪(fǎng)問(wèn)控制方式難以滿(mǎn)足需求。理想的情況是如果權(quán)限需求變動(dòng)不需要修改任何代碼。怎樣才能做到這一點(diǎn)呢?

顯式地訪(fǎng)問(wèn)控制:更好的選擇

從上面的例子我們看到,當(dāng)權(quán)限需求發(fā)生變動(dòng)時(shí),隱式的權(quán)限訪(fǎng)問(wèn)控制方式會(huì)給程序開(kāi)發(fā)帶來(lái)沉重的負(fù)擔(dān)。如果能有一種方式在權(quán)限需求發(fā)生變化時(shí)不需要去修改代碼就能滿(mǎn)足需求那就好了。理解的情況是,即使是正在運(yùn)行的系統(tǒng),你也可以修改權(quán)限策略卻又不影響最終用戶(hù)的使用。當(dāng)你發(fā)現(xiàn)某些錯(cuò)誤的或危險(xiǎn)的安全策略時(shí),你可以迅速地修改策略配置,同時(shí)你的系統(tǒng)還能正常使用,而不需要重構(gòu)代碼重新部署系統(tǒng)。

怎樣才能達(dá)到上面的理想效果呢?我們可以通過(guò)顯式的(明確的)界定我們?cè)趹?yīng)用中能做的操作來(lái)進(jìn)行。

回顧上面隱式的權(quán)限控制的例子,思考一下這些代碼最終的目的,想一下它們最終是要做什么樣的控制?

從根本上說(shuō),這些代碼最終是在保護(hù)資源(項(xiàng)目報(bào)表),是要界定一個(gè)用戶(hù)能對(duì)這些資源進(jìn)行什么樣的操作(查看/修改)。當(dāng)我們將權(quán)限訪(fǎng)問(wèn)控制分解到這種最原始的層次,我們就可以用一種更細(xì)粒度(更富有彈性)的方式來(lái)表達(dá)權(quán)限控制策略。

我們可以修改上面的代碼塊,以基于資源的語(yǔ)義來(lái)更有效地進(jìn)行權(quán)限訪(fǎng)問(wèn)控制:

代碼塊3. 顯式的權(quán)限控制:

if (user.isPermitted("projectReport:view:12345")) {
    //show the project report button
} else {
    //don't show the button
}

上面的例子中,我們可明確地看到我們是在控制什么。不要太在意冒號(hào)分隔的語(yǔ)法,這僅是一個(gè)例子,重點(diǎn)是上面的語(yǔ)句明確地表示了“如果當(dāng)前用戶(hù)允許查看編號(hào)為12345的項(xiàng)目報(bào)表,則顯示項(xiàng)目報(bào)表按鈕”。也就是說(shuō),我們明確地說(shuō)明了一個(gè)用戶(hù)帳號(hào)可對(duì)一個(gè)的資源實(shí)例進(jìn)行的具體的操作。

為什么說(shuō)這種方式更好

上面最后的示例代碼塊與前面的代碼的主要區(qū)別:最后的代碼塊是基于什么是受保護(hù)的, 而不是誰(shuí)可能有能力做什么。看似簡(jiǎn)單的區(qū)別,但后者對(duì)系統(tǒng)開(kāi)發(fā)及部署有著深刻的影響:

  • 更少的代碼重構(gòu):我們是基于系統(tǒng)的功能(系統(tǒng)的資源及對(duì)資源的操作)來(lái)進(jìn)行權(quán)限控制,而相應(yīng)來(lái)說(shuō),系統(tǒng)的功能需求一旦確定下來(lái)后,一段時(shí)間內(nèi)對(duì)它的改動(dòng)相應(yīng)還是比較少的。只是當(dāng)系統(tǒng)的功能需求改變時(shí),才會(huì)涉及到權(quán)限代碼的改變。例如上面提到的查看項(xiàng)目報(bào)表的功能,顯式的權(quán)限控制方式不會(huì)像傳統(tǒng)隱式的RBAC權(quán)限控制那樣因不同的用戶(hù)/角色要進(jìn)行這個(gè)操作就需要重構(gòu)代碼;只要這個(gè)功能存在,顯式的方式的權(quán)限控制代碼是不需要改變的。
  • 更直觀:保護(hù)資源對(duì)象、控制對(duì)資源對(duì)象的操作(對(duì)象及對(duì)象的行為),這樣的權(quán)限控制方式更符合人們的思想習(xí)慣。正因?yàn)榉线@種直觀的思維方式,面向?qū)ο蟮木庉嬎枷爰癛EST通信模型變得非常成功。
  • 更有彈性:上面的示例代碼中沒(méi)有寫(xiě)死哪些用戶(hù)、組或角色可對(duì)資源進(jìn)行什么操作。這意味著它可支持任何安全模型的設(shè)計(jì)。例如,可以將操作(權(quán)限)直接分配給用戶(hù) ,或者他們可以被分配到一個(gè)角色,然后再將角色與用戶(hù)關(guān)聯(lián),或者將多個(gè)角色關(guān)聯(lián)到組(group)上,等等。你完全可以根據(jù)應(yīng)用的特點(diǎn)定制權(quán)限模型。
  • 外部安全策略管理:由于源代碼只反映資源和行為,而不是用戶(hù)、組和角色,這樣資源/行為與用戶(hù)、組、角色的關(guān)聯(lián)可以通過(guò)外部的模塊或?qū)S霉ぞ呋蚬芾砜刂婆_(tái)來(lái)完成。這意味著在權(quán)限需求變化時(shí),開(kāi)發(fā)人員并不需要花費(fèi)時(shí)間來(lái)修改代碼,業(yè)務(wù)分析師甚至最終用戶(hù)就可以通過(guò)相應(yīng)的管理工具修改權(quán)限策略配置。
  • 可在運(yùn)行環(huán)境做修改:因?yàn)榛谫Y源的權(quán)限控制代碼并不依賴(lài)于行為的主體(如組、角色、用色),你并沒(méi)有將行為的主體的字符名詞寫(xiě)在代碼中,所以你甚至可以在程序運(yùn)行的時(shí)候通過(guò)修改主體能對(duì)資源進(jìn)行的操作這樣一些方式,通過(guò)配置的方式就可應(yīng)對(duì)權(quán)限方面需求的變動(dòng),再也不需要像隱式的RBAC方式那樣需要重構(gòu)代碼。
RBAC新解:Resource-Based Access Control

對(duì)于上面列出的諸多好處,我重點(diǎn)要說(shuō)是這種顯式的機(jī)制帶給我們的富有彈性的權(quán)限模型。

如果你仍想保留或模擬傳統(tǒng)的基于角色的權(quán)限訪(fǎng)問(wèn)控制,你可以將權(quán)限(可執(zhí)行的操作)直接分配給某個(gè)角色。這種情況下,你依舊是在使用基于角色的權(quán)限訪(fǎng)問(wèn)控制方式(不同之處在于你需要明確地界定角色中的權(quán)限,而不是傳統(tǒng)的使用角色字符串隱式地進(jìn)行權(quán)限控制)。

但在這種新的模型下,已不必再局限于角色了。你可以將權(quán)限直接分配給用戶(hù)、組或其它你覺(jué)得可以的對(duì)象。

因?yàn)樯厦骘@式地、基于資源的權(quán)限訪(fǎng)問(wèn)控制的諸多好處,或許可以給RBAC一個(gè)新的定義:“Resource-Based Access Control”。只是我的一個(gè)想法:)

現(xiàn)實(shí)世界的例子:Apache Shiro

如果你好奇現(xiàn)實(shí)世界有沒(méi)有被多個(gè)系統(tǒng)使用的基于資源的權(quán)限控制框架,你可以了解一下Apache Shiro。它是一個(gè)java平臺(tái)的現(xiàn)代權(quán)限管理框架。通過(guò)它的權(quán)限(Permission)概念,Shiro很好地支持基于資源的權(quán)限訪(fǎng)問(wèn)控制。

當(dāng)然,并不需要借用Shiro來(lái)理解本文所說(shuō)的一些概念,但Shiro對(duì)理解本文所討論的概念及示例有一定的幫助。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容