权限管理是B端中常见的话题,它规定了用户各自的角色和可使用的职能,也对数据的安全提供了保障。本篇文章中作者结合自身经验,从四部分讲述关于权限管理的设计经验与设计方法。
权限管理是B端产品绕不开的话题,本文总结了我对权限管理的设计经验与设计方法,共分为4个部分:
所有内容均根据自身思考实践及经验借鉴而来,如有错误欢迎指正。
第一章:权限管理的概念梳理权限包括了功能权限和数据权限:
针对功能模块划分用户权限是一种粗颗粒度的划分方式,表现在不同用户可以查看相同的数据,但可执行的操作不同,如线上数据库的数据只有超管可以删除,其他人只能查看;针对数据划分用户权限是一种细颗粒度的划分方式,表现在不同用户进入同一页面/菜单时,可见的数据有差异,如运营经理可以看到部门所有数据,运营人员只能看到自己创建的数据。做权限设计时,首先要分清功能权限和数据权限的界限,不要为了图方便将二者揉起来。
权限管理是用来控制用户可以访问而且只能访问某些资源的系统,根据该定义,我们可以绘制出如下示意图:
可以看出,用户和资源形成了错综复杂的映射关系,很难管理。要解决这一问题,有两种方法:一是减少用户/资源数,显然不切实际,这样就只剩下了一种方法——减少映射关系。
在详细介绍该方法前,我们先来看看数据库中是如何解决查询慢的问题的。大家可以思考一个问题,在【35、27、48、12、29、38、55】这组数列中如何快速找到数字55?
大部分人的第一反应就是一个个遍历,这样一共需要查询7次。而对数据库工程师来说,首先会找到一个媒介来构建这组数列的表示关系(见下图-平衡二叉树),然后再通过简单的判断只用3次就可以找到55了。这个媒介就是数据库中的索引,在数据量巨大的时候,利用索引进行查询的优势十分明显。
如果这个例子不好理解,大家还可以联想下字典中的索引、书籍中的目录或是图书馆中的书架标签,核心思想都是抽象出对象的公共属性,再进行分类管理。
利用这一思想,我们再来回看如何减少用户和资源的映射关系。
对于资源也是同理。
经过以上步骤,原本杂乱无章的映射关系就变得既简约又有层次(见下图),我们只要把权限赋予到抽象出来的虚拟媒介上,就能够大大降低管理的复杂程度。
了解了权限设计的核心思想后,我们以CMS系统的更新为例来阐述权限管理模型的演进。
1. ACL:基于用户的权限管理模型
小王是一家创业公司的产品经理,负责一款CMS系统的设计。起初,网站的所有内容都由公司唯一的运营小红负责,所以小王就对小红的账号开启了所有权限。
这种直接将权限绑定在用户账号上的方式就叫做基于用户的权限管理(ACL)。
2. RBAC:基于角色的权限管理模型
随着运营部门不断发展壮大,每次有新员工入职,小王都要为其单独配置权限,而且无法批量修改,十分繁琐。同时小王发现运营部门分工明确,部分人员负责内容审核,需要为他们开启审核管理的权限;部分人员负责产出内容,需要为他们开启内容管理的权限……这就导致小王经常会做一些重复性的工作。于是小王就想在现有的用户层上再抽象出一层——角色层,只要对角色设置权限,属于该角色的人员就自动拥有这些权限。
这种将权限绑定在角色上,再给用户账号赋予角色的方式就叫做基于角色的权限管理(RBAC),该模型于1992年由美国国家标准与技术研究院组织开发,是目前最通用的权限管理模型,节省了很大的权限维护成本。
GerorgeMason大学的教授Ravi Sandhu于1996年对RBAC模型进行改进,提出了RBAC96模型族,包括RBAC0、RBAC1、RBAC2和RBAC3四个模型。上图代表RBAC0模型,也是其他3个模型的基础。
a. RBAC1:角色继承的RBAC模型
在CMS系统使用了一段时间后,小王发现了一个新问题——系统中存在的角色太多了,因为只要有权限不一样的用户加入系统,就需要新建一个角色,当用户权限分得很细的时候,甚至比ACL还繁琐,于是小王就想着手解决这一问题。
点他发现角色之间存在着类似组织架构一样的上下级关系,比如COO>运营经理>运营主管>运营组长>运营人员>运营实习生,并且上级拥有下级的所有权限,同时可以额外拥有其他权限,于是他在现有的角色基础上又抽象出一层角色等级。
这种在角色中引入上下级关系的RBAC模型就叫做角色继承的RBAC模型(RBAC1),通过给角色分级,高级别的角色可继承低级别角色的权限,一定程度上简化了权限管理工作。
另外角色间的继承关系可分为一般继承关系和受限继承关系。一般继承关系要求角色继承关系是一个绝对偏序关系,允许角色间的多向继承,即下级角色可以拥有多个上级角色,上级角色也可以拥有多个下级角色。而受限继承关系则要求角色继承关系是一个树状结构,角色间只能单向继承,即下级角色只能拥有一个上级角色,但是上级角色可以拥有多个下级角色。
b. RBAC2:角色限制的RBAC模型
过了一段时间,运营经理小红向小王反馈,她的账号竟然可以看到公司的财务账单,经过核查,是小王由于粗心导致给小红的账号多绑了一个财务经理的角色。为了彻底规避这种风险,小王就让开发加了一条判断:当角色是运营经理时不能同时是财务经理。
这种针对角色进行限制的模型就叫做角色限制的RBAC模型(RBAC2),可以把限制具体地分为静态职责分离(SSD)和动态职责分离(DSD):
SSD:
DSD:允许一个用户具有多个角色,但在运行时只能激活其中某些角色,比如BOSS直聘,一个用户既可以是招聘者也可以是应聘者,但同时只能选择一种身份进行操作
c. RBAC3:统一的RBAC模型
RBAC3=RBAC1 RBAC2,既引入了角色间的继承关系,又引入了角色限制关系。
d. 组:完善的RBAC模型
现有的权限管理模型虽然已经对“角色”进行了层级优化,但并没有优化“用户”方,这就意味着每入职一个新员工,小王得单独为其设置权限,还是很麻烦,于是他利用抽象的思想将相同属性的用户进行归类。在公司里,最简单的相同属性就是“部门”了,如果给部门赋予了角色和权限,那么这个部门中的所有用户都有了部门权限,而不需要为每一个用户再单独指定角色。
用户可以分组,权限同样也可以分组。在权限特别多的情况下,可以把同一层级的权限合并为一个权限组,如二级菜单下面有十几个按钮,如果对按钮的操作没有角色限制,可以把这些按钮权限与二级菜单权限合并为一个权限组,然后再把权限组赋予角色就可以了。
“组”概念的引入完善了RBAC模型,在简化操作的同时更贴近了实际业务,便于理解。
3. ABAC:基于属性的权限管理模型
为了内容的安全,运营经理小红向小王提了一个需求:负责内容管理的人员不可以在公司以外的地点发布内容。这可难倒了小王,因为现有的RBAC权限模型仅能对页面/功能/数据赋予权限,没法执行如此精细的权限控制。在查阅相关资料后,小王找到了该问题的解决方法——基于属性的权限管理模型(ABAC)。
ABAC是通过动态计算一个或一组属性是否满足某种条件来进行授权判断的,包括用户属性(如性别年龄)、环境属性(如时间地点)、操作属性(如编辑删除)和对象属性(如一篇文章)。
跟RBAC相比,ABAC能够实现非常灵活的权限控制,可扩延展性也很高,几乎能满足所有类型的需求。但是设计起来比较复杂,而且对于单一属性可以通过编写简单的判断逻辑代替,所以还没有被广泛应用。
权限管理是指为解决某一具体的权限分配问题而采用的方法,比如解决文件的权限分配问题可以采用ACL模型,解决不同年龄段的用户可访问不同类型的电影问题可以采用RBAC ABAC。
而权限体系是指整个系统内采用的权限管理方法的集合。
本系列文章聚焦于单系统内的RBAC权限管理。
1. 唯RBAC论
尽管RBAC已经被广泛应用,但还是要避免一上来就这么做。权限的设计需要评估数据量和业务复杂度,如果预估的数据量特别少,业务又很简单,那完全可以用其他方式。
2. 唯自由配置论
不要认为把权限设置得灵活可配用户就满意了,实际上用户没有那么聪明,他会为角色名称而纠结,看到一系列的权限配置也会不知所措。如果你的业务能够抽象出一些固定角色和统一权限,那就把他们内置起来。
3. 权限越多/越细越好
权限不是功能列表,一味地细化而不注重实际业务,只会增加开发工作量,也不利于用户配置。可以仅选择常用的功能点作为权限配置,也可以将多个功能点抽象为一个权限点,如将“增删改”三个功能抽象为一个“管理”权限点。
第二章:RBAC权限设计的一般步骤1. 罗列所有角色
角色是一种抽象的身份,RBAC离不开角色,因此第一步就是从业务中找到所有可能涉及到的角色。
如果你做的是企业内部管理系统(如ERP、OA),可以参考组织架构找到所有角色(如产品经理、产品助理、项目负责人);其他系统可以通过业务流程找到相关角色,如开展一次线上笔试按流程需要出题老师、题目审查老师、考场管理员、助理、监考老师、巡考老师、考生、阅卷老师。
2. 找到各角色之间的关系
找到所有角色后,第二步就是找出各角色之间的联系。常见的有继承、互斥和共享关系,还可根据实际业务找到角色之间的其他关系:
3. 分析角色是否需要内置以及是否需要隐藏
分析哪些角色我们可以事先定好,哪些角色可由用户自定义。内置角色适用于角色通用且固定、使用频率高的情况,目的是为了简化用户的操作步骤。常把“管理员”角色进行内置,也可根据实际业务选择,比如线上考试系统,“考生管理”菜单就属于内置角色,添加到该列表中的账号只能是“考生”。
同样还要考虑角色是否需要展示给用户,比如一些系统的“超级管理员”就不需要展示给用户。
1. 梳理功能权限
权限分为功能权限和数据权限,其中功能权限又可分为菜单权限和按钮权限。
梳理功能权限一个最简单最实用的办法就是用“功能列表”(下图以“有赞”为例)。
2. 梳理数据权限
数据权限就是系统中存在的数据、资源能够被谁查看和管理。说到数据权限,就不能不提数据库。
1)表/对象
表是包含数据库中所有数据的数据库对象,不同的业务数据存在于不同的表中,如下图从上到下依次为考生表、考场表和考官表。
2)数据
表中存放着二维数据,由行和列组成,如下图的考生表,每一行代表一个考生,每一列代表考生的一个属性。
通过表和数据之间的关系,可以把数据权限分为以下四种情况:
(1)基于系统的数据权限
即系统中的所有表都能被大家看到并管理,也可理解为没有数据权限,比如管理员A、B都能看到并管理所有考生、考官、考场数据。
(2)基于对象的数据权限
即按表划分数据权限,比如管理员A只负责管理考生,管理员B只负责管理考场。
(3)基于行的数据权限
即按表中的数据行划分数据权限,比如管理员A只能管理B学校的考生,但不能管理C学校的考生;或者A部门的经理只能看到A部门职员的周报。
(4)基于列的数据权限
即按表中的数据列划分数据权限,比如管理员A只能看到考生的姓名,而管理员B可以看到考生的姓名、手机号和身份证号。
在梳理数据权限时,可根据实际业务对对象、行和列的数据权限自由组合,比如针对学校A的管理员只能查看学校A的考生及考官的姓名和电话号码,无法查看身份证号这个需求,就使用到了基于行和列的数据权限。
1. 连接角色和功能权限
得到功能列表后,需要跟角色关联在一起,可直接在表后添加角色列,再根据业务对角色是否拥有该功能权限做判断。
2. 连接角色和数据权限
数据权限一般是一系列的规则,可通过文字描述附在上表后。
3. 分析与整理
所有的权限都需要进行分配,但不是每个权限都值得让用户来配置。
在上一步完成后,我们就建立起了所有角色和权限的联系,但上表还不能直接使用,在详细设计之前,还要分析出哪些权限需要用户手动分配,哪些不需要?哪些功能权限可以合并,以便减少用户操作次数?什么场景下数据权限需要可配置?等等这些必须得根据具体的业务进行判断。
仍以“有赞”为例,上图是配置“线索管理”功能权限的实际页面,可以看到它只为用户提供“查看、编辑、转让、放弃、添加资料项、办理试听”这几个功能,其他的功能权限要么都归属于“查看”(添加、办理报名等),要么合并到一个功能里(“批量转让”合并到“转让”)。
理论上是可以把所有的功能权限拿出来让用户配置,但是考虑到用户体验,对权限进行分析和整理是非常有必要的。
第三章:设计功能权限的三板斧通过上述分析,我们得到了最终的角色与权限的关系,接下来就进入到如何设计界面的环节。
设计功能权限离不开最基本的三要素:用户管理、角色管理、权限管理;根据业务的不同,可能还会涉及更复杂的三要素:部门管理、职位管理、菜单管理,在这些之上还会配置不同的版本满足不同的客户需求,这就需要版本管理,下文将会对如何设计这些管理功能进行详细的介绍。
1. 权限管理
权限管理是为角色赋予权限,权限可以内置,也支持用户自定义,权限的配置需要跟角色绑在一起,当权限较简单且相对固定时,可由后端人员写死在代码里或者写死在配置文件里。
2. 角色管理
在“梳理角色”步骤中,我们列出了系统中涉及到的所有角色,“角色管理”就是对这些角色进行线上化的镜像和管理。
按角色的来源可分为用户自定义角色和系统内置角色:
自定义角色:角色的名称和权限都可由用户自由配置,并可任意修改。
内置角色:角色的名称和权限由系统内置好,用户仅可查看无法修改。
设计“角色管理”主要有三个页面:
另外在一些系统里,绑定权限的这个载体不叫“角色”,而是其他的名字,比如在钉钉中叫“管理组”,这里我们要清楚它其实就是“角色”。
3. 用户管理
“用户管理”是用于管理用户信息的,如更改用户角色、创建或删除用户、更改密码和用户信息。
设计“用户管理”主要有两个页面:
同“权限分配”一样,“角色分配”也可以单独放在用户列表中的操作里,这样的交互更专一,但实际没有什么不同。
4. 注意事项
1)用户与角色
需要根据实际业务确定一个用户可以绑定多少个角色。如果可以绑定多个角色,角色之间有没有继承、互斥等关系,功能权限如何划分,这些情况都要提前考虑到。
另外,如果有内置角色,别忘了在内部的“运营管理平台”上设计专门针对“内置角色”的管理功能。
2)角色间的关系
上文中我们列出了角色之间的关系(等级/继承、互斥、共享等),现有的“角色管理”仅能通过一个用户绑定多个角色的方式实现“角色共享”,但没法实现角色间的继承和互斥。
角色间如果有继承关系,可通过下文的“角色组(职位)管理”实现;如果有互斥关系(如会计和审计),对于内置角色可以在代码中写死判断,对于自定义角色,可以让用户另外设置互斥规则。
3)权限组
上文说的分析与整理,其实就是建立权限组,将不必要的权限进行合并,可以简化用户操作。
经过以上步骤,一个基本的权限系统就设计完成了,足够应付80%的场景。
如果是做OA系统的权限管理,或者对灵活度有较高的要求,那么可以了解下进阶版的权限管理三板斧。
1. 部门管理
“部门管理”有三种使用场景。第一种是为了构建企业的组织架构,在这种情况下,部门管理与功能权限没有关系,仅用于归类用户以及分配数据权限。
与功能权限有关系的是下面两种场景:
第二种场景是为了承担“用户组”的作用。在上文介绍RBAC中,如果用户量很多时,将每个用户与角色权限匹配会十分麻烦,这时就需要将用户的共有属性做抽象,在企业中,用户的共有属性可以用部门来表示。
第三种场景是为了承担“角色”的作用,可以为部门直接赋予功能权限,部门中的用户继承该部门的功能权限。若用户也拥有其他角色的权限(如下图的用户2),则实际的功能权限为二者的并集。
另外在分配部门权限时,还需要考虑子部门与父部门的权限关系:可以选择同父部门的权限保持一致,也可以选择子部门继承父部门的权限,并可在其范围内进行编辑,还可以设置完全区别于父部门的权限,这取决于业务的复杂程度。
2. 职位管理
“职位管理”有两种使用场景。第一种是为了完善员工信息,属于一种属性,与功能权限没有关系。
第二种场景与功能权限相关,是为了承担“角色组”的作用。“角色组”是为了满足上下级关系而衍生出的概念,比如“产品经理”应该拥有“产品助理”的所有权限,有了上下级后,再来一个“产品总监”的角色,就不用单独为其设置所有的功能权限,只需将它设为“产品经理”角色的父级,再添加一些特殊的权限即可。
3. 菜单管理
不管是“部门”还是“职位”,解决的都是“用户”和“角色”怎样配置更灵活的问题。在RBAC中还有一个“权限”,目前对权限的管理只介绍了可以通过后端人员写死在代码里或者写死在配置文件里,如果功能权限经常变动,并且自由配置的需求极高,有没有更灵活的办法来管理权限呢?有!就是“菜单管理”。
“菜单管理”又被称为资源管理,是系统资源对外的表现形式。有了“菜单管理”,不仅可以让权限的管理更简单(不需要后端写死),还能够让系统展示更灵活(能够改菜单信息)。
“菜单”分为三类:
设计“菜单管理”主要有两个页面:
1)菜单列表页:
导航菜单是分上下级的,因此可以用树状图表示,常见的菜单属性包括菜单名称、菜单类型(目录、菜单、按钮)、图标、排序、路由地址(浏览器访问菜单的地址)、组件路径(项目的组件文件的路径)、权限标识(查看、编辑、添加等)、是否外链、启用状态和创建时间。除了图中展示的字段,根据业务需求还可以增加“编号、是否打开新页面、是否隐藏、是否缓存(切换到其他菜单当前菜单会进行缓存)”等字段。
2)添加菜单页:
添加目录:目录可以是外链,即点击后跳转到外部地址,必须带上https://或者http://,如果不是外链,则需要填入路由地址,由开发人员给出。
添加菜单:当菜单是外链时,规则同目录,若不是外链,则可选填组件名称、权限标识、组件路径(具体应跟开发讨论系统中是否有涉及)。
添加按钮:添加按钮时,输入权限标识即可。
4. 注意事项
1)谁继承谁
关于“权限继承”,细心的读者会发现我在第一章介绍RBAC时写过:“高级别的角色可继承低级别角色的权限”,而在本章中又说:“子部门可以继承父部门的权限”,是不是冲突了。
其实不然,假设现有AB两个部门,要在它们之上设立一个部门C,则C部门的权限为AB两个部门的并集,从这个角度讲,部门C继承了部门AB的权限,且部门C还可单独设置权限;而如果要给部门A下设一个部门C,部门C会继承部门A的权限,并可在此范围内细化权限。两种说法表达的意思是一样的,都是子级属于父级的权限范围内。
2)功能权限最好不要绑在多个实体上
在上面的介绍中,“部门”、“职位”都可以充当“角色组”直接绑定功能权限,但在实际中却很少有系统这么设计,根本的原因就是没有必要——功能权限最好只绑在一个实体上,意思是说,如果系统中已经有了“角色管理”(为角色设置功能权限),就没有必要再对部门或职位设置功能权限了,同样如果系统中已经为了部门/职位设置了权限,也就没有必要再引出“角色”这个概念了。因为在现实工作中,很少有人在部门、职位和角色上有单独的功能权限,即便是有,也可以通过新建一种“角色”来简化复杂度。如今大部分的OA系统上,职位和部门更多被用于用户归类以及管理数据权限。
3)菜单管理如何实现权限组
需要注意的是,“菜单管理”是精细到系统中最小的操作,可以直接用于分配角色的权限,但如果为了提升用户体验,需要给用户展示出合并后的功能权限时(见下图),则不可在“菜单管理”中直接设置“查看与操作”的按钮,而应该在“菜单管理”之上建一层专门用于展示给用户的功能权限,其中“查看与操作”权限绑定了“新建 编辑 删除”的按钮。
5. 拓展:版本管理
对于SAAS软件,常常会分多个版本来满足不同层次的客户需求,不同版本之间的功能权限会有差异。面对这种情况,可以通过“版本管理”来实现灵活管理(此“版本”非产品迭代的版本)。
设计“版本管理”主要有两个页面:
还有一种更复杂的情况,同一版本的不同客户之间也会有不同的功能权限,那么还需要对每一个客户配置功能限制。
第四章:如何设计数据权限上文讲过数据权限分为四种情况(划分依据详见第二章):
其中”基于系统的数据权限”可以理解为不分数据权限,因为大家看到的和可操作的内容都是一样的;“基于对象的数据权限”可以通过功能权限来实现,比如为用户A分配了客户表的权限,那么A就能够看到并操作所有客户,也就相当于为用户A分配了“客户管理”的功能权限。因此下文主要讨论后两种情况。
另外,数据权限的分配也可分为内置和用户自定义两种。内置数据权限属于系统中写死的规则,如本校老师只能看到本校的资源,公共库中的资源所有学校的老师均可看到,销售人员创建的线索只有自己能够管理等等,内置数据权限过于简单,也不在本文讨论范围内。
基于行的数据权限分为两种情况,一种是为对象(部门/角色)分配数据,如上级部门可以管理下级部门的所有数据;还可以将数据分配给对象,如共享文件。
1. 为对象分配数据
1)无组织架构
对于不涉及组织架构的系统,数据权限的设计比较简单,在为角色配置权限时,一并展示可分配的数据权限即可。
分配数据权限的前提是分配了对应的功能权限,比如要让计算机老师只能管理“软件工程”的所有题目,前提是要给老师开启“题库管理”的功能权限,否则老师连“题库管理”都看不到,何来管理其中的题目数据。当然功能权限不一定非要手动分配,也可以内置,比如蓝湖,加入的成员默认开启了“团队文件”的菜单,所以在配置时只需要展示数据权限列表。
2)有组织架构
可以通过设置“管理范围”实现上下级之间的数据权限控制。比如针对上级可以看到下级的题库这一需求,可以设置一个“部门负责人”角色,并设置管理范围为“所在部门和下级部门”,然后将公司领导、各部门负责人都添加成这个角色,即可实现该需求。
也可以通过设置“管理范围”实现跨部门之间的数据权限控制。比如针对研发部负责人可以看到IT部门题目的需求,则可以新建一个角色,管理范围选择“特定部门”,并勾选“研发部和IT部”。
还可以通过设置“管理范围”实现同部门之间的数据权限控制。比如都是产品部,产品组长能看到下属创建的题目,但看不到产品总监创建的题目,产品助理只能看到自己创建的题目,这时就需要用到职位的层级关系。
2. 为数据分配对象
可以理解为把数据直接共享给某个角色/部门,常用于文件/资源的共享,下图是钉钉上对文件的权限管理。
如果说数据权限是对功能权限在纵向的扩展,那么字段权限就是在横向的扩展。因为设置数据列权限可以禁止指定角色对某些敏感字段的访问,如身份证号、交易金额等。
设计“列权限”主要有两个页面:
全文完。
最后做个总结,本文第一章讲了权限管理的基本概念,第二章讲了RBAC权限管理在设计前的分析步骤,第三章和第四章分别讲了如何设计功能权限(权限、角色、用户、部门、职位、菜单、版本)和数据权限(基于行和基于列)。文中部分图片手机看不清,可用电脑端打开,内容如有错误欢迎指正。
本文由 @产品乱弹 原创发布于人人都是产品经理,未经作者许可,禁止转载
题图来自 unsplash,基于 CC0 协议
该文观点仅代表作者本人,人人都是产品经理平台仅提供信息存储空间服务。
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved