简介
常规权限系统设计
材料1
基本主体:用户 角色 资源。为用户赋予角色,角色操作资源,角色将用户与资源隔离。
从资源的角度说,权限管理分为
- 功能权限管理:资源的的新增、删除和修改
-
数据权限管理
- 比如资源有地区维度,比如上海地区、北京地区。
- 比如资源有部门维度,比如行政部、技术部
- 维度之间有交集,横向关系。比如上海的行政部
- 维度有包含关系,纵向关系,比如具备上海的权限,则自动具备浦东和宝山的权限
功能权限的控制:
- 我自己曾经一个简单实现,
uid,资源id,optype(新增、删除等)
- 一些材料展示,类似于
uid,url
数据权限设计,建议使用规则引擎。
具体的技术操作上,功能权限可以在系统上加filter,对某个url 没有权限,则直接滤掉。(在材料3中称为功能操作表)
材料2
功能权限决定可以对资源采取何种操作,数据权限决定了用户/角色能不能看到这些资源。
经过用户、角色、资源的抽象后。用户本身有一定的属性,比如所在地区。资源本身有一定的属性,比如资源所在的地区、创建资源的人。所谓权限问题,就是用户与资源间属性的匹配问题。
那么从一个用户身份出发,我们可以拿到uid、所在地区,角色id。这些数据作为一个变量,拼接成一个规则字符串(比如json),这些规则字符串是一个条件树。
{
groups:
[
{
rules[
{
field: current role id,
op: in,
value:2,6
typo: int
}
]
op:and
},
{
rules[
{
filed: current role id,
op:equal,
value:7,
type:int
},{
field: employee id,
op:equal,
value: current employ id
type:number
}
]
op:and
}
]
op:or
}
条件树附加在资源身上,用以识别哪些用户可以访问该资源:
- 可以被角色id为2或6的用户看到
- 假设资源有创建者id,那么如果当前用户角色id为7,并且创建了该资源,则可以看到
- 一个权限系统的两个基本过程:授权和鉴权
- 角色可以用来做功能权限,做数据权限的话,会导致角色数量非常多
- 授权
材料3
2018.3.27
说明:A-B 表,表示A表、B表、AB关联表。
就是用户通过角色与权限进行关联,此处用户与角色好理解,难点就是 “权限”在系统中如何描述。
- 用户-权限
- 用户-角色-权限,角色就是一组权限的集合,不直接将权限授予用户
-
用户-角色-权限-资源。假设一个权限描述为“删除文件A”,则应包括文件表、权限表、文件权限关联表。
- 权限表,权限id、权限类型(增删改查)。
- 文件(文件是资源的一种)表,略
- 文件权限关联表, id、权限id、文件id
那么最后查一个用户有没有某个文件的权限
- 查询用户的角色id
- 查询角色id 对应的权限id
- 查询文件权限关联表,根据权限id看看有没有的对应的文件id。
也就是,查询用户 有没有操作文件的权限,落脚点在,文件权限关联表上,有没有对应的记录。
类似的,还有一个权限-功能操作表,功能操作表中,每条记录有一个url 前缀。通过关联表 可以查到 用户是否可以访问该url。
材料4
权限设计的方式有哪些?
- 以“用户”为单位的权限设计。适用的业务场景为:使用该系统的人之中,存在很多拥有同一类权限的人。
- 以“权限”为单位的权限设计。当使用该系统的人之中,很多人的权限是不一样的
- 以“用户”与“权限”结合的权限设计
自身实践
2017.12.29
笔者曾负责一个组件系统,用户可以新增组件,并对组件进行一些操作。具备以下要求:
- 管理员具有上帝视角,可以看到任何组件,进行任何操作
- 组件具有不同的类型,有的类型只能应用在一个os中(android或ios),有的可以应用在任何os中。因此,按照组件被应用的os、以及文件类型,也会有专门的管理员。比如android 管理员,ios 管理员等
- 一般开发只可以操作他本人创建的组件。但因为伙伴开发的需要,两个开发要都能够操作某一个组件。
- 操作组件的权限分为新增、修改和删除
最终关于权限这块的实现是
- 管理员和开发分开,开发者的权限管理按照功能权限设计,
uid、资源id、操作类型(crud)
- 管理员的权限管理,只具体到是否可以看到资源,如果能看到资源即拥有对资源进行操作的crud权限
- 从管理员的角度出发,定义数据规则。比如“osType=android”即表示该用户具备查看所有适用于android 系统的组件。
该权限系统能这么设计,也是因为权限控制比较简单:
- 用户角色单纯的划分为管理员和开发两种,所以直接省了角色表
- 管理员和开发是平级的,只是管理员的权限更大一些
- 管理员没有功能权限的要求,即只要是管理员就可以crud
代码接口
-
方法上加注解,用来描述该方法 谁可以执行
@PrivilegedOperation("admin=true") public void delete(Device device){ ... }
- 使用filter, 根据请求url + uid 判断是否具有操作权限
- 硬编码
-
拦截所有的资源访问方法,或者说在所有的资源操作方法执行之前 “塞入” 一个处理逻辑,进行权限判断。比如
@PrivilegedOperation public void delete(@PrivilegedResourceId(resouce="device") id="deviceId" Device device){ ... }
通过 PrivilegedOperation 拦截方法的执行,通过PrivilegedResourceId 描述资源的id
审批流程(未完成)
2018.4.23 新增
权限管理系统伴随的,通常会有一个审批流程系统,相关设计参见审批流程数据库设计
数据库表 设计中,也会有类和实例的关系
- flow:id,name
- node:id,flow_id,prev,next,handlers
- flow_example:id,title,uid(发起者),create_at,status(未发起,正在流转,已结束)
-
process: id,node_id,uid(操作者),handle_at,flow_example_id
- flow + node 将一个流程的作用及先后 步骤 规定好
- flow_example 是一个流程的实例
- process,描述 在当前 实例下,进行到哪一个步骤
小结
权限系统涉及的主体:用户、角色、资源
权限分为
-
功能权限,描述uid可以对资源id进行哪些类型的操作。功能权限的管控有两种粒度:
- 比如增删改查,直接跟uid 绑定。
- 以develop(查询 + 新增 + 修改)、guest(查询)、master(查询 + 新增 + 修改)、owner(增删改查 + 授权) 等角色来 表示功能权限
-
数据权限,描述哪些用户可以看到哪些资源。
- 数据规则可以附加在用户身上,描述用户可以看到哪些资源。比如
isAdmin=true
或者andoridAdmin=true
。 - 也可以附加在资源身上,描述资源可以被哪些用户访问。比如每次新增一个资源,都记录一个
id、uid/roleid、资源id
前者将用户规则加在用户上,只适合简单系统,查询麻烦,更新资源方便。后者更符合“角色将用户与资源隔离的精神”,但每次资源操作都需要更新 用户与资源的关联关系。查询方便,更新资源麻烦。
- 数据规则可以附加在用户身上,描述用户可以看到哪些资源。比如