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进行权限管理——第二节 策略存储相关推荐

  1. beego利用casbin进行权限管理——第一节 起步、测试

    beego利用casbin进行权限管理--第一节 起步.测试 beego利用casbin进行权限管理--第二节 策略存储 beego利用casbin进行权限管理--第三节 策略查询 beego利用ca ...

  2. beego利用casbin进行权限管理——第三节 策略查询

    beego利用casbin进行权限管理--第一节 起步.测试 beego利用casbin进行权限管理--第二节 策略存储 beego利用casbin进行权限管理--第三节 策略查询 beego利用ca ...

  3. (王道408考研操作系统)第三章内存管理-第二节3:页面置换算法2

    上接: (王道408考研操作系统)第三章内存管理-第二节2:页面置换算法1 文章目录 一:时钟置换算法(CLOCK) (1)简单时钟置换算法 (2)改进型时钟置换算法 二:页面置换算法总结 一:时钟置 ...

  4. java8421码,关于用Java程序实现8421码权限管理 第二部分

    这两天做完了以前,CRM项目中,设计权限这快的代码,仅供大家学习参考. 本权限管理部分设计三部分: 第一部分 数据库部分 第二部分 权限类 第三部分 分配权限部分 第四部分 页面控制部分 在这里我主要 ...

  5. (王道408考研操作系统)第三章内存管理-第二节1:虚拟内存管理基本概念

    文章目录 一:传统存储管理方式的弊端 二:局部性原理与高速缓冲技术Cache (1)Cache基本原理 (2)局部性原理 三:虚拟内存的定义和特征 (1)定义 (2)特征 四:虚拟内存实现 内存管理需 ...

  6. (王道408考研操作系统)第三章内存管理-第二节2:请求分页管理方式

    文章目录 一:页表机制 二:缺页中断机构 三:地址变换机构 虚拟内存的实现需要建立在离散分配的内存管理方式的基础上.主要有以下三种 请求分页存储管理 请求分段存储管理 请求段页式存储管理 与传统的非连 ...

  7. (王道408考研操作系统)第二章进程管理-第二节4:调度算法详解2(RR、HPF和MFQ)

    文章目录 一:时间片轮转调度算法(RR) 二:优先级调度算法(HPF) 三:多级反馈队列调度算法(MFQ) 总结 进程调度算法也称为CPU调度算法,操作系统内存在着多种调度算法,有的调度算法适用于作业 ...

  8. spring2.5.6整合hibernate3.3.2_Annotation声明式事务管理-第二节

    一.根据第一节项目稍作修改即可,看截图需要修改的地方.    二.按画红线处依次贴出代码 UserDAOImpl.java package com.iskyshop.dao.impl;import j ...

  9. ABP+AdminLTE+Bootstrap Table权限管理系统第二节--在ABP的基础做数据库脚本处理

    返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 第一点,上一篇文章中我们讲到codefirst中一些问题包括如图,codefirst在每次执行命令的时候会生成新的 ...

最新文章

  1. BIOS英文报错详解;你虽会做系统,但你会看BIOS英文报错吗,仅供大家参考学习。...
  2. 如何找回由于IO设备错误移动磁盘的文件
  3. 转:Android之 MTP框架和流程分析
  4. 避免在Swift Struct中使用闭包
  5. 网易Q2季报图解:游戏营收重回百亿 净利同比降29%
  6. 希望找到计算机系的好期刊的影响因子的排序?并作为选刊依据?选SJR就足够了
  7. case 日期when 范围_多个日期段如何分组 case when convert等用法
  8. python编写界面遍历_python和pywin32实现窗口查找、遍历和点击
  9. 女生会 P 的可不仅仅是丰胸和瘦腿......
  10. Tomcat 配置 login 和 gas
  11. Let‘s Fluent:更顺滑的MyBatis
  12. ggplot2绘图如何根据一个变量即区分颜色又区分深浅?
  13. 解决WARN TaskSchedulerImpl: Initial job has not accepted any resources;
  14. node-glob学习
  15. Angular Js对象的拷贝复制
  16. python 库总结_最近用的python 库总结
  17. Java中的守护程序线程
  18. 关于架设流媒体服务器与DRM加密问题
  19. 孩子一生的教育纪录片
  20. 计算机功能键盘使用方法,键盘的使用方法介绍 键盘上都有哪些功能按键

热门文章

  1. 基于Centos+Docker+Kubeadm的高可用集群设计
  2. sql查询字段重复的数据 并且修改数据某个字段
  3. CentOS7.3源码编译MYSQL5.7
  4. animeganv2
  5. idea ctrl 左键进入方法后,如何返回上一个方法
  6. Labview通过NIopc与施耐德plc通信
  7. softmax matlab代码,MATLAB实现softmax
  8. 串口低频刷卡密码键盘ID卡发卡器YD791开关设置选择
  9. 普利姆算法和克鲁斯卡尔算法解决最小生成树问题
  10. 基于SSH的酒店预订系统