访问控制
ReactGO 提供基于角色和菜单码的访问控制,这种方式简单清晰,也足够应对大部分的情况, 如果你的系统需要更精细多变的访问控制,那么可以实现自己的访问控制,例如使用 OPA 编写访问规则。
概念
┌────────┐ ┌─────────────┐
│ User A ├─────► ┌─────────┐ ┌►│ Menu 1 │
└────────┘ ┌► │ Role A ├──────┘ └─────────────┘
│ └─────────┤
┌────────┐ │ └───────►┌─────────────┐
│ User B ├────┘ ┌─────────┐ │ Menu 2 │
└────────┘ │ Role B ├─────┐ └─────────────┘
└─────────┘ │
┌────────┐ ▲ │ ┌─────────────┐
│ User C ├───────────┘ └► │ Menu 3 │
└────────┘ └─────────────┘
用户和角色
每个用户可以关联一个角色,也只能关联一个角色,角色用来确定最终的访问权限。 角色本身只是一堆菜单访问权限的集合,如果它没有分配给用户,那么它本身没有任何意义。
角色和菜单
角色是菜单的权限集合,一个角色可以包含 0 到多个菜单的访问权限。所谓菜单,对应的就是某个具体的
url,例如'用户管理'菜单的 url 是 /system/user
,一般我们说菜单的时候,不会说 url,因为
url 只是实现细节,访问控制与 url 的关系不是很大,而是通过菜单代码来控制。
菜单和代码
每个菜单用一个代码来完成访问控制,例如“用户管理”的菜单代码是 9000
,如果一个菜单没有代码,
那么就不能使用 ReactGO 内置的访问控制功能。菜单在 route/sidebar/codes.js
文件中定义。
保留菜单代码
菜单代码由 3 到 4 个数字构成,8000
以上的区域以及 911
是保留给系统的,不要使用。
你应该尽可能的使用 3 个数字菜单代码,因为更容易记忆。
菜单权限
每个菜单可以定义 3 个权限,读
、写
、管理
,也可以说是 访问
,修改
、管理
,
意思是一样的。
定义上,读是最基本的权限,如果没有读权限,那么基本上只能看见菜单,但是打开的话得不到任何数据, 也不能做任何操作。 有读权限后,可以访问数据,但是要修改数据,就需要写权限。 管理权限属于一种模糊权限,没有明确的定义,你可以根据自己的业务来适当的使用这个权限。
所有上面的 3 个权限,只是一种预设的定义,怎么使用完全在于你,参考后端访问控制部分。
前端访问控制
前端访问控制主要设计到几个部分:
- 菜单代码定义;
- 角色控制配置;
- 用户关联角色;
其中 2, 3 都已经内置,你无需做任何工作,你需要做的是 1。
举个例子,假设你要新增一个业务办理的页面,你希望这个页面能够纳入访问控制,
那么你需要为这个业务定义一个菜单,在 src/route/sidebar/codes.js
文件中增加一行:
urlCodes = {
...
1111: { title: '业务办理', to: '/yewu' },
...
}
这行的意思是说,增加了一个菜单,代码为 1111
,标题是业务办理,增加这行之后,如果你访问
访问控制
菜单,你会发现这个菜单可以纳入访问控制了。
配置好前端的访问控制后,如果用户现在访问 /yewu
(假设你已经写好了页面),
即使用户没有分配访问权限,也照样可以访问,这是为什么呢?这是因为真正执行权限检查是在后端,
后端现在还没有增加访问控制。
顺便提一下,菜单代码不仅仅用于访问控制,同时也用于快速导航,就是你按下 Ctrl
+ K
时输入的那个数字。
后端访问控制
后端是真正执行访问控制检查的地方,主要是用三个函数:
acl.AllowRead(code)
,acl.AllowWrite(code)
,以及 acl.AllowAdmin(code)
。
菜单代码
参数 code
对应前端定义的菜单代码,除了你知道这个代码的含义外,系统其他地方都不会去检查,
这非常的宽松,同时也意味着如果你写错了 code
,系统是不会有任何提示的。
如果要修改菜单代码,记得前后端都要修改,如果你的菜单非常多,那么需要花点时间来设计菜单代码,
最好写在纸上。
这三个函数是中间件函数,可以这样用(用在组上):
group := up.Group("/task", acl.AllowRead(1111))
这样整个"组"都需要 1111
的 READ 权限才能访问。
也可以这样用(用在部分路由上):
// 这里不需要 WRITE 权限即可访问
// ...
group.Use(acl.AllowWrite(1111))
// 后续的访问需要 WRITE 权限才能访问
// ...
还可以这样用(用在单个路由上):
group.POST("/admin", Proc, acl.AllowAdmin(1111))
这个的意思是只针对 /admin
这个路由实施 ADMIN 权限控制。
中间键函数
可能你对这行语句有点疑惑:
group.POST("/admin", Proc, acl.AllowAdmin(code))
虽然看起来 acl.AllowAdmin()
写在 Proc
的后面,但实际上 acl.AllowAdmin()
会在 Proc
之前执行。
但是对于 Use()
就不一样了,Use() 只会影响它之后的路由,正如它的文档所说的那样:
Use adds middleware to the chain which is run after router.
更多信息请参考 Echo 文档。