訪問控制是指區分不同使用者對不同資源的訪問能力,在應用系統中通常叫做許可權管理
在做任何多使用者系統的時候,使用者許可權管理都是整個系統中必不可少的部分,並且許可權設計要做到既安全又清晰是一件不太容易的事情。
根據不同的場景,許可權管理可以設計出各種不同的模型。
今天就給各位介紹一個訪問控制框架Casbin以及PERM元模型。
元模型 PERM
如果,在做系統設計時,針對每一個資源和每一個使用者都編寫訪問規則將會是一個工作量很大的事情,並且對於動態變化的資源和使用者,這樣做是不可行的。因此我們需要定義一系列規則,這些規則的組合就是一個訪問控制模型。
PERM模型是由4個基礎(Policy,Effect,Request,Matchers)描述各個資源和使用者之間的相互關係。
Request 請求
定義了請求引數。一個基本的請求是一個元組物件,至少包含subject(訪問實體), object(訪問的資源)和 action(訪問方法)。
r={sub, obj,act}
它其實就是定義了傳入訪問控制匹配函式的引數名和順序。
Policy 策略
定義訪問策略的模型。其實就是定義Policy規則文件中各欄位的名稱和順序。
p={sub, obj, act}
或 p={sub, obj, act, eft}
注意:如果不定義 eft(策略結果),那麼將不會去讀策略檔案中的結果欄位,並將匹配的策略結果都預設為allow
。
Matchers 匹配規則
Request和Policy的匹配規則。
例如: m = r.sub == p.sub && r.act == p.act && r.obj == p.obj
這條簡單又常見的匹配規則的意思就是,請求的引數(實體、資源和方法)都相等即在策略中能找到,那麼返回策略結果(p.eft)。策略結果會儲存在p.eft
中。
Effect
用於將給定請求與最終結果匹配的策略組合/減少的策略的模型。可以理解為,對Matchers匹配後的結果再進行一次邏輯組合判斷的模型。
例如:e = some(where(p.eft == allow))
這句的意思是指,如果匹配策略結果p.eft
存在(some
) allow
的結果,那麼最終結果就為 真
再看個例子:e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
這個例子組合的邏輯含義是:如果有匹配出結果為alllow
的策略並且沒有匹配出結果為deny
的策略則結果為真,換句話說,就是匹配的策略都為allow
時才為真,如果有任何deny
,都為假 (更簡單的說當allow
和deny
同時存在時,deny
優先)
以上時PERM的模型定義的說明,接下來,用Casbin實戰一下
Casbin訪問控制需要兩個東西:訪問控制模型檔案和策略檔案,模型檔案就是上文描述的內容。
下圖說明了如何使用基於 PERM 的模型授權請求。
PERM
建立一個完整的模型檔案
建立一個perm.conf檔案,內容如下
# Request definition
[request_definition]
r = sub, obj, act
# Policy definition
[policy_definition]
p = sub, obj, act, eft # 這裡我們定義了eft,不使用預設值
# Policy effect
[policy_effect]
e = some(where (p.eft == allow)) && !some(where (p.eft == deny)) # 這裡使用了deny優先
# Matchers
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act #最簡單的匹配規則。請求的引數與策略引數一致時獲得策略結果
注意程式碼中的註釋
建立一個policy.csv檔案, 其中的每個欄位的定義就如perm中[policy_definition]中定義的順序:
p, zeta, data1, read, allow
p, bob, data2, write, allow
p, zeta, data2, write, deny
p, zeta, data2, write, allow
p 代表策略組名稱,就是metchers裡對應的那個p。後面的zeta,data, read, allow對應的就是策略定義中的sub,obj,act和策略結果eft。
假如,request引數在策略檔案中能夠匹配(zeta,data1和read),那麼結果為allow;
假如,request引數在策略檔案中能夠匹配(zeta,data2,write),那麼結果為deny,同時也匹配另一條策略結果為allow,根據policy_effect的定義,依然識別為假。
接下來用Go程式碼檢驗一下
建立main.go 程式碼如下:
package main
import (
“fmt”
“github.com/casbin/casbin”
)
func main() {
//通過策略檔案和模型配置穿件一個casbin訪問控制例項
e := casbin.NewEnforcer(“./perm.conf”, “./policy.csv”)
//定義各種sub,obj和act的陣列
subs := []string{“bob”, “zeta”}
objs := []string{“data1”, “data2”}
acts := []string{“read”, “write”}
//遍歷組合sub,obj,act並列印出對應策略匹配結果。
for _, sub := range subs {
for _, obj := range objs {
for _, act := range acts {
fmt.Println(sub, “/“, obj, “/“, act, “=“, e.Enforce(sub, obj, act))
}
}
}
}
這段Go程式碼很簡單,組合每一種sub、obj和act,然後列印出訪問控制的結果驗證我們的策略檔案和模型的設計。
執行結果為:
bob / data1 / read = false
bob / data1 / write = false
bob / data2 / read = false
bob / data2 / write = true
zeta / data1 / read = true
zeta / data1 / write = false
zeta / data2 / read = false
zeta / data2 / write = false
bob的策略很簡單,只有data2的write結果為allow,因此其餘都是false,結果正確;
zeta對data1的read結果為allow,對data2的write同時有allow和denny(根絕policy_effect定義的deny優先),因此結果zeta也只對 data1的read 為true,結果正確。
這樣,我們就使用Casbin和PERM建立了一個基礎的訪問控制模型設計和策略。
在實際應用上,如果我們做的是一個Web應用,可以將路由作為obj,請求方式Method作為act,登入使用者的角色作為sub,在每一次請求時,把這3個引數傳遞給e.Enforce
, 就可以實現對Web頁面和請求介面的許可權控制管理,非常方便。
高階
儲存
Casbin除了能夠通過策略檔案和模型配置檔案設定訪問控制外,還可以適配資料庫模式,將策略和模型儲存在資料庫中,更適合大型複雜的軟體系統的許可權管理。
函式
文中的模型配置沒有使用額外的函式,但是在實際應用中,對與資源的匹配模式,action的匹配模式可能會用到更高階的匹配方法。利用函式是最佳實踐方式。
API
本作品採用《CC 協議》,轉載必須註明作者和本文連結