• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

gin-vue-admin学习后端篇—— 4.Casbin权限管理

武飞扬头像
学徒。
帮助1

对于此项目的权限管理。在前面阅读中间件源码时候提到了这个。经过这几周的研究,逐渐理解了此项目的权限管理系统

1. 基础知识

在讲解本项目的权限管理系统前,可以先了解下业界主要有的方案:ACL,DAC,MAC,RBAC,ABAC

1.1 ACL,DAC,MAC

ACL是最简单的权限控制模型,里边主要是记录 某个用户 可以对 某个资源某个操作 ,如

Tony  /manager/list  GET

这个意思为名叫Tony的用户可以对路径为/manager/list的api执行GET操作。 这里可以将用户称之为subject,资源称之为object,动作称之为action

对于DAC模型,是基于ACL的。与ACL的区别是subject 可以将自己拥有的权限赋予给其他subject。如上方的例子,Tony可以将这个接口的权限赋予给其他用户。

MAC模型的话,也是基于ACL的。与ACL区别是安全性更高,是双向授权。在指定subject 可以对object 执行 action操作的同时,必须也要指定对应的object可以被subject执行action操作。用上方例子来说就是这样的

Tony  /manager/list  GET # tony可以对/manager/list接口执行get请求
/manager/list  Tony  GET # /manager/list接口的get方法可以被tony执行

只有同时满足了这两点,这个授权策略才算成功。

1.2 RBAC,ABAC

RBAC权限模型应该是当前最普及的,本项目使用的就是RBAC策略 (ps: 我感觉是伪RBAC,原因在后边解释)

这个与上方提到的ACL策略相比,新增了个一个 role(角色)的概念。在ACL中的subject一般来说都是用户。在RBAC中subject一般指的是role。比如说我们有个工作平台,平台上有很多个方向的事务处理。 对于每个方向可能有对应的方向管理员,而对于整个平台也可能有整个平台的管理员。而且这里的“管理员”也不只是一个人。我们只需要指定某个角色有什么权限即可。然后再指定哪个用户是哪个角色。

policy:
Manage /manager/list GET

role: 
tony Manage
marry Manage

如上方,就代表tony和marry都有对/manager/list接口的 GET 执行权限。

对于ABAC模型就更为复杂,相比于RBAC又增加了属性的概念,这样的话粒度比RBAC更细。如某个服务器的8000-9000端口可以被部门为xx部的Manage角色执行xx操作。具体可以参考其他博文详细了解。


2. gin-vue-admin的权限系统

此项目中使用的权限管理模型是上方介绍的RBAC,但上方也说过,此项目的RBAC在我理解看来是伪RBAC。具体可以一步一步来看。

2.1 项目代码

func CasbinHandler() gin.HandlerFunc {
	return func(c *gin.Context) {
		waitUse, _ := utils.GetClaims(c)
		// 获取请求的PATH
		obj := c.Request.URL.Path
		// 获取请求方法
		act := c.Request.Method
		// 获取用户的角色
		sub := waitUse.AuthorityId
		e := casbinService.Casbin()
		// 判断策略中是否存在
		success, _ := e.Enforce(sub, obj, act)
		if global.GVA_CONFIG.System.Env == "develop" || success {
			c.Next()
		} else {
			response.FailWithDetailed(gin.H{}, "权限不足", c)
			c.Abort()
			return
		}
	}
}
学新通

这个是项目中casbin中间件的代码。在这个中间中主要的运行流程为获取到请求的PATH,Method和用户角色。 casbin拿到这三个数据后去数据库中查询是否满足权限要求,若满足则执行c.Next()下一个中间件,若不满足则直接返回并提示权限不足。

总体流程看起来并不复杂,可以点进去casbinService.Casbin() 中查看如何使用casbin的。

学新通

这里主要理解的是中间的一大串字符串

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && keyMatch2(r.obj,p.obj) && r.act == p.act

request_definition表示访问请求,下面的r = sub, obj, act分别表示用户,资源,动作

policy_definition表示策略,这里的p = sub, obj, act 表示的意思与上方的r的一致。

然后先跳过中间两个,直接看最下面的mathers:

m = r.sub == p.sub && keyMatch2(r.obj,p.obj) && r.act == p.act ,从文本描述大概可知。当请求的用户(sub)和行为(act)与策略中的一致,并且url两者路径相匹配(keyMatch2)则表示验证通过。注:对于keyMatch2()官方是如下描述的:

学新通

所以只要是访问p.obj所表示url的资源,均可以通过这个keyMatch2的验证。

现在回过头来看上面的两个,对于role_definition,表示角色的定义,即RBAC权限模型里的role,后边的g = _, _ 表示角色继承关系的前项和后项,即前项继承后项角色的权限。这里看起来会有点生硬,我直接拿官网给的例子:

p, data2_admin, data2, read
g, alice, data2_admin

第1行代表data2_admin可以使用read操作访问data2

第2行代表alice是data2_admin角色中的一员,则alice就可以使用read操作访问data2。

这里的规则语法,我描述的可能简单了些,具体可参考 官方文档

对于具体的的规则配置,可查看数据库中的casbin_rule

学新通

这里可以以第一行来举例,意思为 888 可以给 /base/login 发送POST请求。在用户使用过程中,如果888给这个接口发送POST请求时,就会触发casbin中间件来验证是否有这个权限

2.2 伪RBAC?

拿上方的例子来说,这里的 888 并不是实际的用户名,在项目中可以称之为AuthorityId,可以理解为角色id。每个用户可以有多个角色。对于我认为的理想的RBAC应该是这样的,假设有一个场景:

用户小明拥有两个角色:管理员、普通用户, 有个API为user/:resource来获取某个用户的详细信息,方法为GET那么作为小明这个用户在输入的入参应该是 userIdApiType RBAC内部会通过对应的userId来找到小明对应的角色,然后查看拥有的角色是否有对应的权限。

而该项目的RBAC实际上是这样的:小明在前端主动选择使用哪个角色,然后传给后端的入参是AuthorityIdApiType,假如小明自己选择了 普通用户角色 访问user/:resource这个接口就会提示没有权限。

学新通

前端通过点击切换角色后,会请求后端/user/setUserAuthority的api

学新通

然后后端收到请求后,会去数据库中把当前用户使用的AuthorityId更换为用户选择的id,并重新生成token(这是因为token中包含了AuthorityId信息,所以需要重新生成),详情请看下方代码

学新通

从我的理解来看,对于RBAC里,发来的请求中sub应该为用户,而此项目的sub直接就为角色,这样就跳过了RBAC里的用户转角色的步骤。所以,如果只从Casbin中的记录来看,该项目使用的权限系统倒更像是ACL,只是基于ACL做了比较多的前置操作,但核心还是ACL。

当然,这样做肯定有这样做的原因。刚才我们是从纯后端的角度来看权限管理,但如果我们从前端角度来看,就会发现这样做的好处了,这个留给以后阅读前端代码时候再说。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfbkjk
系列文章
更多 icon
同类精品
更多 icon
继续加载