天天看點

RBAC新解 - 基于資源的權限管理

1、什麼是角色

當說到程式的權限管理時,人們往往想到角色這一概念。角色是代表一系列可執行的操作或責任的實體,用于限定你在軟體系統中能做什麼、不能做什麼。使用者帳号往往與角色相關聯,是以,一個使用者在軟體系統中能做什麼取決于與之關聯的各個角色。

例如,一個使用者以關聯了”項目管理者”角色的帳号登入系統,那這個使用者就可以做項目管理者能做的所有事情――如列出項目中的應用、管理項目組成員、産生項目報表等。

從這個意義上來說,角色更多的是一種行為的概念:它表示使用者能在系統中進行的操作。

2、基于角色的通路控制(role-based access control)

既然角色代表了可執行的操作這一概念,一個合乎邏輯的做法是在軟體開發中使用角色來控制對軟體功能和資料的通路。你可能已經猜到,這種權限控制方法就叫基于角色的通路控制(role-based access control),或簡稱為rbac。

有兩種正在實踐中使用的rbac通路控制方式:隐式(模糊)的方式和顯示(明确)的方式。

今天依舊有大量的軟體應用是使用隐式的通路控制方式。但我肯定的說,顯示的通路控制方式更适合于目前的軟體應用。

3、隐式的通路控制

前面提到,角色代表一系列的可執行的操作。但我們如何知道一個角色到底關聯了哪些可執行的操作呢?

答案是:目前的大多數應用,你并能不明确的知道一個角色到底關聯了哪些可執行操作。可能你心裡是清楚的(你知道一個有”管理者”角色的使用者可以鎖定使用者帳号、進行系統配置;一個關聯了”消費者”這一角色的使用者可在網站上進行商品選購),但這些系統并沒有明确定義一個角色到底包含了哪些可執行的行為。

拿”項目管理者”來說,系統中并沒有對”項目管理者”能進行什麼樣的操作進行明确定義,它僅是一個字元串名詞。開發人員通常将這個名詞寫在程式裡以進行通路控制。例如,判斷一個使用者是否能檢視項目報表,程式員可能會編碼如下:

在上面的示例代表中,開發人員判斷使用者是否有”項目管理者”角色來決定是否顯示檢視項目報表按鈕。請注意上面的代碼,它并沒有明确語句來定義”項目管理者”這一角色到底包含哪些可執行的行為,它隻是假設一個關聯了項目管理者角色的使用者可檢視項目報表,而開發人員也是基于這一假設來寫if/else語句。

4、脆弱的權限政策

像上面的權限通路控制是非常脆弱的。一個極小的權限方面的需求的變動都可能導緻上面的代碼需要重新修改。

舉例來說,假如某一天這個開發團隊被告知:“哦,順便說一下,我們需要一個’部門管理者’角色,他們也可以檢視項目報表。請做到這一點。”

這種情況下,開發人員需要找到上面的代碼塊并将其修改為:

随後,開發人員需要更新他的測試用例、重新編譯系統,還可能需要重走軟體品質控制(qa)流程,然後再重新部署上線。這一切僅僅是因為一個微小的權限方面的需求變動!

後面如果需求方又回來告訴你說我們又有另一個角色可檢視報表,或是前面關于”部門管理者可檢視報表”的需求不再需要了,豈不把人累死了。

如果需求方要求動态地建立、删除角色以便他們自己配置角色,又該如何應對呢?

像上面的情況,這種隐式的(靜态字元串)形式的基于角色的通路控制方式難以滿足需求。理想的情況是如果權限需求變動不需要修改任何代碼。怎樣才能做到這一點呢?

5、顯式地通路控制:更好的選擇

從上面的例子我們看到,當權限需求發生變動時,隐式的權限通路控制方式會給程式開發帶來沉重的負擔。如果能有一種方式在權限需求發生變化時不需要去修改代碼就能滿足需求那就好了。了解的情況是,即使是正在運作的系統,你也可以修改權限政策卻又不影響最終使用者的使用。當你發現某些錯誤的或危險的安全政策時,你可以迅速地修改政策配置,同時你的系統還能正常使用,而不需要重構代碼重新部署系統。

怎樣才能達到上面的理想效果呢?我們可以通過顯式的(明确的)界定我們在應用中能做的操作來進行。

回顧上面隐式的權限控制的例子,思考一下這些代碼最終的目的,想一下它們最終是要做什麼樣的控制?

從根本上說,這些代碼最終是在保護資源(項目報表),是要界定一個使用者能對這些資源進行什麼樣的操作(檢視/修改)。當我們将權限通路控制分解到這種最原始的層次,我們就可以用一種更細粒度(更富有彈性)的方式來表達權限控制政策。

我們可以修改上面的代碼塊,以基于資源的語義來更有效地進行權限通路控制:

上面的例子中,我們可明确地看到我們是在控制什麼。不要太在意冒号分隔的文法,這僅是一個例子,重點是上面的語句明确地表示了“如果目前使用者允許檢視編号為12345的項目報表,則顯示項目報表按鈕”。也就是說,我們明确地說明了一個使用者帳号可對一個的資源執行個體進行的具體的操作。

6、為什麼說這種方式更好

上面最後的示例代碼塊與前面的代碼的主要差別:最後的代碼塊是基于什麼是受保護的, 而不是誰可能有能力做什麼。看似簡單的差別,但後者對系統開發及部署有着深刻的影響:

7、rbac新解:resource-based access control

對于上面列出的諸多好處,我重點要說是這種顯式的機制帶給我們的富有彈性的權限模型。

如果你仍想保留或模拟傳統的基于角色的權限通路控制,你可以将權限(可執行的操作)直接配置設定給某個角色。這種情況下,你依舊是在使用基于角色的權限通路控制方式(不同之處在于你需要明确地界定角色中的權限,而不是傳統的使用角色字元串隐式地進行權限控制)。

但在這種新的模型下,已不必再局限于角色了。你可以将權限直接配置設定給使用者、組或其它你覺得可以的對象。

因為上面顯式地、基于資源的權限通路控制的諸多好處,或許可以給rbac一個新的定義:“resource-based access control”。隻是我的一個想法:)

8、現實世界的例子:apache shiro

如果你好奇現實世界有沒有被多個系統使用的基于資源的權限控制架構,你可以了解一下apache shiro。它是一個java平台的現代權限管理架構。通過它的權限(permission)概念,shiro很好地支援基于資源的權限通路控制。

當然,并不需要借用shiro來了解本文所說的一些概念,但shiro對了解本文所讨論的概念及示例有一定的幫助。