beego利用casbin进行权限管理——第二节 策略存储
beego利用casbin进行权限管理——第一节 起步、测试
beego利用casbin进行权限管理——第二节 策略存储
beego利用casbin进行权限管理——第三节 策略查询
beego利用casbin进行权限管理——第四节 策略更新
beego利用casbin进行权限管理——第五节 策略更新(续)
EngineerCMS工程师知识(资料)管理系统的github地址。该系统正是充分利用了casbin进行树状目录赋权。
上一节讲到修改casbin目录下beego-orm-adapter里的adapter.go,这里要继续修改一下,否则会把数据库冲掉。
接下来进行用户的角色分配。
代码如下,其实就是生成策略——把用户对应角色写入数据库casbin_rule
//添加用户角色
//先删除用户所有角色
func (c *RoleController) UserRole() {//要支持批量分配角色,循环用户iduid := c.GetString("uid") //先删除用户的权限e.DeleteRolesForUser(uid) //下节介绍这个//再添加,如果没有选择,相当于删除了全部角色ids := c.GetString("ids") //roleidif ids != "" {array := strings.Split(ids, ",")for _, v1 := range array {e.AddGroupingPolicy(uid, "role_"+v1) //management_api.go//应该用AddRoleForUser()//rbac_api.go}// a.SavePolicy(e.GetModel())//autosave默认是true// [{0 p 12 1 } {0 g 8 1 } {0 g 7 1// } {0 g 7 2 } {0 g 5 1 } {0 g 5 2 }]// lines := [7][4]string{{"0", "p", "100", "1"}, {"0", "p", "101", "1"}}// _, err := a.o.InsertMulti(len(lines), lines)// return err}c.Data["json"] = "ok"c.ServeJSON()
}
当然,前提是你先定义了角色。
数据库中的样子是这样的:
接下来是给角色赋予对某某目录下(v1/v2/v3/*)资源的各种权限。
conf目录下的rbac_model.conf如下
[request_definition]
r = sub, obj, act, suf [policy_definition]
p = sub, obj, act, suf[role_definition]
g = _, _[policy_effect]
e = some(where (p.eft == allow))[matchers]
m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && regexMatch(r.suf, p.suf) && r.act == p.act
接下来给角色赋予项目目录下资源的请求权限,
代码:
//给角色赋项目目录的权限
func (c *RoleController) RolePermission() {roleids := c.GetString("roleids")rolearray := strings.Split(roleids, ",")// beego.Info(rolearray)permissionids := c.GetString("permissionids")permissionarray := strings.Split(permissionids, ",")// beego.Info(permissionarray)sufids := c.GetString("sufids")sufarray := strings.Split(sufids, ",")treeids := c.GetString("treeids") //项目目录idtreearray := strings.Split(treeids, ",")// beego.Info(treearray)treenodeids := c.GetString("treenodeids") //项目目录的nodeid 0.0.0-0.0.1-0.1.0-0.1.0treenodearray := strings.Split(treenodeids, ",")// beego.Info(treenodearray)// treeids := c.GetString("tree")//json字符串解析到结构体,以便进行追加// var tree []Tree// err := json.Unmarshal([]byte(treeids), &tree)// if err != nil {// beego.Error(err)// }var success boolvar nodeidint intvar projurl, action, suf stringvar err error//取出项目目录的顶级var nodesid, nodesids []stringif len(treenodearray) > 1 {nodesids, err = highest(treenodearray, nodesid, 0)if err != nil {beego.Error(err)}}// beego.Info(nodesids)for _, v1 := range rolearray {for _, v2 := range permissionarray {//定义读取、添加、修改、删除switch v2 {case "添加成果":action = "POST"suf = ".*"case "编辑成果":action = "UPDATE"suf = ".*"case "删除成果":action = "DELETE"suf = ".*"case "读取成果":action = "GET"for _, v4 := range sufarray {if v4 == "任意" {suf = ".*"break} else if v4 == "" { //用户没展开则读取不到table4的selectsuf = "(?i:pdf)"} else {suf = "(?i:" + v4 + ")"}}}for _, v3 := range nodesids {nodeidint, err = strconv.Atoi(v3)if err != nil {beego.Error(err)}//id转成64位pidNum, err := strconv.ParseInt(treearray[nodeidint], 10, 64)if err != nil {beego.Error(err)}//根据projid取出路径proj, err := m.GetProj(pidNum)if err != nil {beego.Error(err)}if proj.ParentIdPath == "" {projurl = "/" + strconv.FormatInt(proj.Id, 10) + "/*"} else {projurl = "/" + strings.Replace(proj.ParentIdPath, "-", "/", -1) + "/" + treearray[nodeidint] + "/*"}success = e.AddPolicy(v1, projurl, action, suf)}}}if success == true {c.Data["json"] = "ok"} else {c.Data["json"] = "wrong"}c.ServeJSON()
}//迭代查出最高级的树状目录
func highest(nodeid []string, nodesid []string, i int) (nodesid1 []string, err error) {if i == 0 {nodesid = append(nodesid, "0")}var i1 intfor i1 = i; i1 < len(nodeid)-1; i1++ {matched, err := regexp.MatchString("(?i:"+nodeid[i]+")", nodeid[i1+1])// fmt.Println(matched)if err != nil {beego.Error(err)}if !matched {i = i1 + 1nodesid = append(nodesid, strconv.Itoa(i1+1))break} else {if i == len(nodeid)-2 {return nodesid, err}}}if i1 < len(nodeid)-1 {nodesid, err = highest(nodeid, nodesid, i)}return nodesid, err
}
上面求树状目录最高级的目的是:我们选中某一级目录,其下级自动选中了,这些目录id传递到服务端后,我们只需要往策略里存入最高级的就行了,然后用keymatch匹配路由即可。比如,策略里运行访问v1/v2/*,那么,你访问v1/v2/v3/*也是可以的了。
查出用户的权限:
func (c *RoleController) Get() {id := c.Ctx.Input.Param(":id")c.Data["Id"] = idc.Data["Ip"] = c.Ctx.Input.IP()// if id == "" { //如果id为空,则查询roles, err := m.GetRoles()if err != nil {beego.Error(err)}if id != "" {//查出用户的角色,处于勾选状态userroles := e.GetRolesForUser(id)userrole := make([]Userrole, 0)var level stringlevel = "2"for _, v1 := range roles {for _, v2 := range userroles {ridNum, err := strconv.ParseInt(v2, 10, 64)if err != nil {beego.Error(err)}if ridNum == v1.Id {level = "1"}}aa := make([]Userrole, 1)aa[0].Id = v1.Idaa[0].Rolename = v1.Rolenameaa[0].Rolenumber = v1.Rolenumberaa[0].Level = leveluserrole = append(userrole, aa...)aa = make([]Userrole, 0)level = "2"}c.Data["json"] = userrolec.ServeJSON()}c.Data["json"] = rolesc.ServeJSON()
}
其他说明:
1.用户id和角色id重复问题。因为p策略可能对应的是user,也可能对应的role,所以当2者id相同的时候,就分不清是用户还是角色了。所以要给角色id前加role_字样。
(我这里存入的是用户id对应角色id,然后是角色对应的路由和请求权限,问题来了,当用户id和角色id相同的时候,即时这个用户不在角色里,这个用户直接具有了请求的权限,因为casbin不分辨用户和和角色。解决方案,是将角色id加上_role,比如1_role,在服务端再做处理。)
这里讲用户和角色重名的问题。
// Create Role and User
// Casbin only stores the user-role mapping.
// Do not use the same name for a user and a role inside a RBAC system,
// because Casbin recognizes users and roles as strings, and there's no way for
// Casbin to know whether you are specifying user alice or role alice.
// You can simply solve it by using role_alice.
https://github.com/luk4z7/middleware-acl/blob/9764e0c0bcc1804272921c34da0148caa2448d63/src/middleware/service/role/role.go#L19-L22
2.只需要addpolicy(实时存入map)就行了,而不需要savepolicy(存入数据库),因为自动存入数据库了。这里讲自动存入数据库,好处是避免了重复存储。
https://github.com/casbin/casbin/wiki/AutoSave
beego利用casbin进行权限管理——第二节 策略存储相关推荐
- beego利用casbin进行权限管理——第一节 起步、测试
beego利用casbin进行权限管理--第一节 起步.测试 beego利用casbin进行权限管理--第二节 策略存储 beego利用casbin进行权限管理--第三节 策略查询 beego利用ca ...
- beego利用casbin进行权限管理——第三节 策略查询
beego利用casbin进行权限管理--第一节 起步.测试 beego利用casbin进行权限管理--第二节 策略存储 beego利用casbin进行权限管理--第三节 策略查询 beego利用ca ...
- (王道408考研操作系统)第三章内存管理-第二节3:页面置换算法2
上接: (王道408考研操作系统)第三章内存管理-第二节2:页面置换算法1 文章目录 一:时钟置换算法(CLOCK) (1)简单时钟置换算法 (2)改进型时钟置换算法 二:页面置换算法总结 一:时钟置 ...
- java8421码,关于用Java程序实现8421码权限管理 第二部分
这两天做完了以前,CRM项目中,设计权限这快的代码,仅供大家学习参考. 本权限管理部分设计三部分: 第一部分 数据库部分 第二部分 权限类 第三部分 分配权限部分 第四部分 页面控制部分 在这里我主要 ...
- (王道408考研操作系统)第三章内存管理-第二节1:虚拟内存管理基本概念
文章目录 一:传统存储管理方式的弊端 二:局部性原理与高速缓冲技术Cache (1)Cache基本原理 (2)局部性原理 三:虚拟内存的定义和特征 (1)定义 (2)特征 四:虚拟内存实现 内存管理需 ...
- (王道408考研操作系统)第三章内存管理-第二节2:请求分页管理方式
文章目录 一:页表机制 二:缺页中断机构 三:地址变换机构 虚拟内存的实现需要建立在离散分配的内存管理方式的基础上.主要有以下三种 请求分页存储管理 请求分段存储管理 请求段页式存储管理 与传统的非连 ...
- (王道408考研操作系统)第二章进程管理-第二节4:调度算法详解2(RR、HPF和MFQ)
文章目录 一:时间片轮转调度算法(RR) 二:优先级调度算法(HPF) 三:多级反馈队列调度算法(MFQ) 总结 进程调度算法也称为CPU调度算法,操作系统内存在着多种调度算法,有的调度算法适用于作业 ...
- spring2.5.6整合hibernate3.3.2_Annotation声明式事务管理-第二节
一.根据第一节项目稍作修改即可,看截图需要修改的地方. 二.按画红线处依次贴出代码 UserDAOImpl.java package com.iskyshop.dao.impl;import j ...
- ABP+AdminLTE+Bootstrap Table权限管理系统第二节--在ABP的基础做数据库脚本处理
返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 第一点,上一篇文章中我们讲到codefirst中一些问题包括如图,codefirst在每次执行命令的时候会生成新的 ...
最新文章
- BIOS英文报错详解;你虽会做系统,但你会看BIOS英文报错吗,仅供大家参考学习。...
- 如何找回由于IO设备错误移动磁盘的文件
- 转:Android之 MTP框架和流程分析
- 避免在Swift Struct中使用闭包
- 网易Q2季报图解:游戏营收重回百亿 净利同比降29%
- 希望找到计算机系的好期刊的影响因子的排序?并作为选刊依据?选SJR就足够了
- case 日期when 范围_多个日期段如何分组 case when convert等用法
- python编写界面遍历_python和pywin32实现窗口查找、遍历和点击
- 女生会 P 的可不仅仅是丰胸和瘦腿......
- Tomcat 配置 login 和 gas
- Let‘s Fluent:更顺滑的MyBatis
- ggplot2绘图如何根据一个变量即区分颜色又区分深浅?
- 解决WARN TaskSchedulerImpl: Initial job has not accepted any resources;
- node-glob学习
- Angular Js对象的拷贝复制
- python 库总结_最近用的python 库总结
- Java中的守护程序线程
- 关于架设流媒体服务器与DRM加密问题
- 孩子一生的教育纪录片
- 计算机功能键盘使用方法,键盘的使用方法介绍 键盘上都有哪些功能按键