1. 程式人生 > >beego利用casbin進行權限管理——第四節 策略更新

beego利用casbin進行權限管理——第四節 策略更新

casbin onlyoffcie engineercms 權限設計

移步到這裏
近4個月沒有更新這個系列。這個系列都是我粗淺的理解,其中我感覺有些的思路並非最優,並不合主流概念,因為我沒去學習rbac之類的概念,僅供參考。特別是對於權限設計的處理方式,casbin是盡量用它自己的查詢方式,因為那是直接查(增、刪、改)內存(map),而不應該去查(增、刪、改)數據庫,這點必須避免,這個系列文章中很多犯這樣的錯誤,閱讀時,應該根據自己的場景,去回避犯這種錯誤。

這次後半部分借助我剛寫完的onlyoffice的權限設計,這個權限設計總體感覺蠻新穎的,是仿照onlyoffice community寫的,對文檔的賦權,無論是用戶還是角色,每個對應4種權限,一氣呵成,我使用bootstrap table的x-editable以及select2等進行下拉選擇,實時批量設置和單獨切換權限,非常自由隨性。

策略更新包含用戶角色更新,用戶或角色的權限更新。casbin的rbac_api.go和management_api.go中的方法,似乎分成幾個“層次”:比如addrole和addpermission,這種專用的;AddNamedPolicy類似這種通用的。

再比如GetPermissionsForUser,它不同於enforce(),後者能夠實現:user屬於role,user具備訪問data1的權限,role具備訪問data2的權限,此時用enforce(user,data2),結果是true,但是用GetPermissionsForUser(user),它取不到role的data2。 只能用 先取出user的所有角色,再循環,取出每個角色具備的權限。

[plain] view plain copy
roles := e.GetRolesForUser(useridstring) //取出用戶的所有角色
for , w := range roles {
roleRes = e.GetPermissionsForUser(w) //取出角色的所有權限
for
, k := range roleRes {
言歸正傳,策略修改總的思路應該是這樣:

1.要更新一個用戶的角色,先把這個用戶的角色全部刪掉,然後重新添加這個用戶的角色。

2.更新用戶(或角色)的權限,先把這個用戶對於某個文件的權限全部刪掉,再重新添加,道理一樣。

首先是用戶和角色的修改:下圖,點擊用戶,下面顯示這個用戶具有的角色,並勾選上。

當修改勾選後,再保存,後端先用e.DeleteRolesForUser(uid)將這個用戶的所有角色刪除。再根據前段選中的傳入後端進行循環添加。

[plain] view plain copy
//添加用戶角色
//先刪除用戶所有角色
func (c *RoleController) UserRole() {
//要支持批量分配角色,循環用戶id
uid := c.GetString("uid") //secofficeid
//先刪除用戶的權限
e.DeleteRolesForUser(uid) //數據庫沒有刪掉!
//刪除數據庫中角色中的用戶
o := orm.NewOrm()
qs := o.QueryTable("casbinrule")
, err := qs.Filter("PType", "g").Filter("v0", uid).Delete()
if err != nil {
beego.Error(err)
}
//再添加,如果沒有選擇,相當於刪除了全部角色
ids := c.GetString("ids") //roleid
if ids != "" {
array := strings.Split(ids, ",")
for , v1 := range array {
e.AddGroupingPolicy(uid, "role
"+v1)
//應該用AddRoleForUser()//rbac_api.go
}

}  
c.Data["json"] = "ok"  
c.ServeJSON()  

}
onlyoffice中對於某個文檔的權限更新

選中一個文檔,點擊權限按鈕,顯示這個文檔的用戶、角色和對應的權限。

對於/onlyoffice/26這個文檔,當刪除或增加用戶、角色後,傳到後臺,先用RemoveFilteredPolicy刪掉所有的CasbinRul表中v1為/onlyoffice/26的策略。

然後再根據傳過來的策略重新存入。因為這裏是把用戶和角色放在一個表格裏,所以要做一下區分,角色id加上role_字樣,以示區別。

[plain] view plain copy
e.RemoveFilteredPolicy(1, "/onlyoffice/"+strconv.FormatInt(attachments[0].Id, 10))

:= orm.NewOrm()
qs := o.QueryTable("casbinrule")
, err = qs.Filter("v1", "/onlyoffice/"+strconv.FormatInt(attachments[0].Id, 10)).Delete()
if err != nil {
beego.Error(err)
}
/再添加permission
for , v1 := range rolepermission {
// beego.Info(v1.Id)
if v1.Rolenumber != "" { //存儲角色id
success = e.AddPolicy("role
"+strconv.FormatInt(v1.Id, 10), "/onlyoffice/"+strconv.FormatInt(attachments[0].Id, 10), v1.Permission, suf)
} else { //存儲用戶id
success = e.AddPolicy(strconv.FormatInt(v1.Id, 10), "/onlyoffice/"+strconv.FormatInt(attachments[0].Id, 10), v1.Permission, suf)
}
//這裏應該用AddPermissionForUser(),來自casbin\rbac_api.go
}
RemovePolicy和RemoveGroupingPolicy可以根據自己的場景來使用。

上面例子,本來用casbin的方法,刪除了內存中的策略,相應的它會自動刪除數據庫中的數據,但是暫時解決不了,導致數據庫的數據不會自動刪除,所以分別添加了一段代碼,用於刪除數據庫數據。

casbin用於判斷用戶的的權限是很方便的。但由於場景很多,比如有時候要顯示一個登錄用戶對各個資源的的權限(下圖):

有時管理員要知道一個資源所有的用戶和角色,並對應擁有的權限,如下圖。

還有個幾個常見的問題:

1.用戶的權限permission(action)用1、2、3、4來表示還是用get,post,……因為有時候要分等級和優先,如果再加一個字段不一定需要。比如,對於一個文檔,全部權限規定為1,評論為2,只讀為3,不允許為4。設置權限的時候,直接給這個用戶設置權限為只讀3,而這個用戶屬於角色role,這個role對這個文檔權限是1,那這個用戶應該是最大權限優先。所以用1234比較合適,轉成int後可以做比對,取最小的。

2.casbin對於admin應該沒有特殊的處理吧,和普通角色一樣來設置吧。

3.另外casbin對於ip區段支持。這個我以前還在網上找了一段ip區段處理的代碼,好像是某個ip掃描器代碼,先把區段變成一個個ip,對應端口號,然後寫入map,在內存中。竟然類似casbin的方式。

接下來有個不成熟的想法:把casbin的example裏的conf和csv一一對應地放到一個文件中,加上註釋,可能的話配上增刪改等方法。這樣方便初學者能夠直接進入例子,或者自己的場景能直接在這裏找到例子。另外就是一些casbin的思想,我都是東拼西湊理解的,並非代表官方思路,它的處理手段背後為啥要這樣?

beego利用casbin進行權限管理——第四節 策略更新