后端产品的权限系统设计

Posted 琦彦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了后端产品的权限系统设计相关的知识,希望对你有一定的参考价值。

后端产品的权限系统设计

前言

随着互联网的快速发展,B 端行业也逐渐崛起,很多企业管理中使用的软件我们通常称其为 B 端管理系统,而在 B 端系统中“权限管理”是必不可少的功能,不同的系统中权限的应用复杂程度不一样,都是根据实际产品以及需求情况而设置合理的权限。

了解现有情况再进行设计了。

谈到权限控制的设计,需要先理清楚定义和原理。到权限的本质什么?其实是:用户与可以进行的行为的关联关系

这句话中有3个关键词:用户、行为、关联关系。

参考RBAC模型,结合这些年的工作经验,觉得可以通过以下方式实现对页面权限、操作权限与数据权限的管理,我把这种方式称作:“三位一体法“。换言之,三位一体:用户+行为+关联关系=用户权限

衍生出如下几个问题

关于用户

  • 用户是怎么分类的(用户角色)

  • 用户和用户之间是否有关系?如果有,是什么关系?关系是什么结构的?

    • 如公司组织架构那种层级分明的树形结构

关于行为

  • 怎么将行为分类(一般来说按照行为目的区分、按照行为业务类别区分、按照行为与系统的交互类型区分)

    • 例如,按照行为与系统的交互类型区分

      • 数据权限:指的是用户有权操作的那部分数据(读、写)
      • 功能权限:对使用人群在功能修改使用等方面权利的限制
  • 行为之间是否有层级和依赖关系,是怎么样的依赖关系

关于关联关系

  • 是一对一还是一对多,如果有父子层级之分,是继承关系还是独立存在。

这是概念层的问题,具体到工作的设计当中,用于梳理需求会有一些帮助,主要还是用于梳理基础概念。

一句话概括就是:权限系统维护的是人和可进行行为的关联关系。

常见的访问控制模型

权限 二字从字面上可拆分为 权力+限制,从使用者的角度来说,也就是在限制的范围内正确地行驶权力,而站在设计者的角度来解读,则是通过合理的手段控制使用者能访问到他们能够访问到的资源。

在权限设计领域,最常见的权限模型有以下几种:

  • DAC (Discretionary Access Control) : 自主访问控制, 系统会识别用户,然后根据被操作对象(Subject)的权限控制列表(ACL: Access Control List)或者权限控制矩阵(ACL: Access Control Matrix)的信息来决定用户的是否能对其进行哪些操作,例如读取或修改。
  • MAC (Mandatory Access Control) : 强制访问控制, 为了弥补DAC权限控制过于分散的问题而诞生的。在MAC的设计中,每一个对象都有一些权限标识,每个用户同样也会有一些权限标识,而用户能否对该对象进行操作取决于双方的权限标识的关系,这个限制判断通常是由系统硬性限制的。
  • ACL(Access Control List)访问控制列表 用户 -> 权限
  • RBAC(Role-Based Access Control):基于 角色 的权限控制 用户 -> 角色 -> 权限
  • ABAC(Attribute-Based Access Control):基于 属性 的权限控制,该模型根据特殊的规则分配权限 (用户、资源、对象属性)-> 权限
  • PBAC(Policy-Based Access Control):基于 策略 的权限控制,用户(组)隶属于角色,角色隶属于资源(项目)用户 -> 角色 -> (资源/项目 + 权限)

DAC 模型, 因为用户能自主地将自己拥有的权限授予其他用户,所以DAC模型可以任意传递权限,用户能间接获得本不具有的访问权限,因此DAC模型的安全性较低,不能给系统充分的数据保护。

MAC 模型,非常适合机密机构或者其他等级观念强烈的行业,但对于类似商业服务系统,则因为不够灵活而不能适用。

ACL 模型,权限能直接赋予用户,例如将查看订单列表(权限)赋予某位运营人员(用户)。但是这种模式的缺点在于,但用户量达到一定量级的时候,那么就需要对每个用户都进行一次授权操作,那么这个工作量就会相当大。具体来说,为每个用户维护了单独的权限列表,当需要分配权限、收回权限时,需要修改对应用户的权限信息。

因此就出现了 RBAC 模型,这是软件设计中最常用的权限管理模型,相比于 ACL 模型,RBAC 模型在用户与权限之间多了一个元素「角色」,通过权限关联角色、角色关联用户的方法来间接地赋予用户权限,从而实现用户与权限的解耦。

相对于RBAC , ABAC模型非常的灵活,也非常的难实现。

不同于常见的将用户通过某种方式关联到权限的方式,ABAC则是通过动态计算一个或一组属性是否满足某种条件来进行授权判断的(可以编写简单的逻辑)。属性通常来说分为四类:用户属性(如用户年龄),环境属性(如当前时间),操作属性(如读取)和对象属性(如一篇文章,又称资源属性),所以理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。

例如规则:“允许所有班主任在上课时间自由进出校门”这条规则,其中,“班主任”是用户的角色属性,“上课时间”是环境属性,“进出”是操作属性,而“校门”就是对象属性了。

ABAC非常的灵活,但是实现也是非常的难。这其中涉及到逻辑的动态执行,数据动态过滤等,更加具体就是动态拼接SQL语句(使用ORM的话就是动态组装对应ORM的查询语句)。

RBAC的存在的一个问题, 在于它不是一个自动的过程,这意味着需要手动对其进行管理。从本质上讲,角色是与授权对象的静态连接,因此,需要进行的任何更改(添加,删除和更新用户的访问权限)都必须由IT经理来完成。掌握谁应该访问哪些资源是一个复杂又令人困惑的过程。因此,当用户请求新权限时,IT经理必须检查以确保允许该用户访问。危险在于,只要涉及“人为因素”,就很容易引入错误。

PBAC的指导原则是,设置策略、用户配置文件和环境条件必须符合允许访问的标准。 由于PBAC支持运行时授权,因此它是动态的,并具有允许实时进行更改的能力。无需维护不断变化的用户角色的存储库,无需从特定组中添加或删除单个用户,也无需在公司的员工状态和职责发生变化时不断维护对资源的授权。由于PBAC是自动过程,因此可以减少与人工干预有关的风险。但存在不能直观看出用户和资源的访问关系,需要实时计算,较多规则会有性能问题。

Access Control Policy定义优点缺点例子
RBAC根据角色确定访问权限,用户可以绑定不同角色。管理较为灵活,目前的主流模型角色是与授权对象的静态连接,
角色是手动配置
管理员角色、编辑角色、读者角色拥有不同的权限,新增加一个用户只需要设定相应角色,不需要依次设置对每个操作的权限
DAC由资源的所有者、某些组的成员确定访问权限可以基于数据/资源自主控制权限控制较为分散,不易管理文章的发布者指定哪些其它用户可以对这篇文章进行哪些操作
MAC给信息添加敏感程度标签,与用户的敏感程度标签进行对比确定能否访问。而标签是由管理员设定适用于安全要求较高如军事相关的系统不够灵活A 资源拥有敏感标签B,C用户拥有敏感标签D,如果D不小于B,则B可以访问A
ABAC/PBAC根据用户属性、资源属性动态计算访问权限动态管理、支持不同颗粒度的权限控制不能直观看出用户和资源的访问关系,需要实时计算,较多规则会有性能问题满足A条件的用户可以对满足B条件的资源进行C操作

综合来说, 现代系统对于权限的设置基本上都是建立在 RBAC 权限模型上的、扩展的,下面我会通过介绍 RBAC 权限模型的概念以及结合实际业务情况列举权限设置的应用。

什么是 RBAC 权限模型?

RBAC 是 Role-BasedAccess Control 的英文缩写,意思是基于角色的访问控制。RBAC 认为权限授权实际上是 Who、What、How 的问题。在 RBAC 模型中,who、what、how 构成了访问权限三元组,也就是 Who 对 What 进行 How 的操作,也就是“主体”对“客体”的操作。其中 who 是权限的拥有者或主体(例如:User、Role),what 是资源或对象(Resource、Class)。

简单的理解其理念就是将“角色”这个概念赋予用户,在系统中用户与权限之间通过角色进行关联,以这样的方法来实现灵活配置。

RBAC 其实是一种分析模型,主要分为:基本模型 RBAC0角色分层模型 RBAC1角色限制模型 RBAC2统一模型 RBAC3

RBAC 权限模型是基于角色的权限控制。模型中有几个关键的术语:

  • 用户:系统接口及访问的操作者
  • 权限:能够访问某接口或者做某操作的授权资格
  • 角色:具有一类相同操作权限的用户的总称

1. RBAC0

RBAC0 是 RBAC 权限模型的核心思想,RBAC1、RBAC2、RBAC3 都是在 RBAC0 上进行扩展的。

RBAC0 是由四部分构成:用户、角色、会话、许可。

  • 用户和角色的含义很简单,通过字面意思即可明白,
  • 会话:指用户被赋予角色的过程,称之为会话或者是说激活角色;
  • 许可: 就是角色拥有的权限(操作和和被控制的对象),简单的说就是用户可使用的功能或者可查看的数据。

用户与角色是多对多的关系,用户与会话是一对一的关系,会话与角色是一对多的关系,角色与许可是多对多的关系。

2. RBAC1

RBAC1 是在 RBAC0 权限模型的基础上,在角色中加入了继承的概念,添加了继承的概念后,角色就有了上下级或者等级关系。

举例:集团权责清单下包含的角色有:系统管理员、总部权责管理员、区域权责管理员、普通用户,当管理方式向下兼容时,就可以采用 RBAC1 的继承关系来实现权限的设置。

上层角色拥有下层的所有角色的权限,且上层角色可拥有额外的权限

3. RBAC2

RBAC2 是在 RBAC0 权限模型的基础上,在用户和角色以及会话和角色之间分别加入了约束的概念(职责分离),职责分离指的是同一个人不能拥有两种特定的权限(例如财务部的纳入和支出,或者运动员和裁判员等等)。

用户和角色的约束有以下几种形式:

  • 互斥角色:同一个用户在两个互斥角色中只能选择一个(也会存在一个用户拥有多个角色情况,但是需要通过切换用户角色来实现对不同业务操作)
  • 基数约束:一个用户拥有的角色是有限的,一个角色拥有的许可也是有限的
  • 先决条件约束:用户想要获得高级角色,首先必须拥有低级角色

会话和角色之间的约束,可以动态的约束用户拥有的角色,例如一个用户可以拥有两个角色,但是运行时只能激活一个角色。

例如:如下系统, 用户与角色就采用了约束的概念,超级管理员只允许只有一个

4. RBAC3

RBAC3 是 RBAC1 与 RBAC2 的合集,所以 RBAC3 包含继承和约束。

为什么要引用 RBAC 权限模型?

RBAC 中具有角色的概念,如果没有角色这个概念,那么在系统中,每个用户都需要单独设置权限,而系统中所涉及到的功能权限和数据权限都非常多,每个用户都单独设置权限对于维护权限的管理员来说无疑是一件繁琐且工作量巨大的任务。

而引入角色这个概念后,我们只需要给系统设置不同的角色,给角色赋予权限,再将用户与角色关联,这样用户所关联的角色就直接拥有了该角色下的所有权限。

例如:用户 1~用户 8 分别拥有以下权限,不同用户具有相同权限的我用不同的颜色做了区分,如下图:

在没有引入 RBAC 权限模型的情况下,用户与权限的关系图可采用下图展示,每个用户分别设置对应的权限,即便是具有相同权限的用户也需要多次设置权限。

引入 RBAC 权限模型及引入了角色的概念,根据上面表格的统计,用户 1、用户 3、用户 5、用户 8 拥有的权限相同,用户 2、用户 6、用户 7 拥有相同的权限,用户 4 是独立的权限,所以我们这里可以根据数据统计,以及实际的需求情况,可以建立三个不同的角色,角色 A、角色 B、角色 C,三个角色分别对应三组用户不同的权限,如下图所示:

对应的上面的案例表格我们就可以调整为含有角色列的数据表,这样便可以清楚的知道每个用户所对应的角色及权限。

通过引用 RBAC 权限模型后,对于系统中大量的用户的权限设置可以更好的建立管理,角色的引入让具有相同权限的用户可以统一关联到相同的角色中,这样只需要在系统中设置一次角色的权限,后续的用户便可以直接关联这些角色,这样就省去了重复设置权限的过程,对于大型平台的应用上,用户的数量成千上万,这样就可避免在设置权限这项工作上浪费大量的时间。

RBAC 权限模型的优势

(1)将抽象的权限具像化,分配权限时不用再思考抽象问题。

举例:新入职的初级销售小张找管理员开账号,管理员不用纠结到底要不要给小张开「查看部门销量」的权限,只需要把小张的账号指向「初级销售」的角色即可,这个角色有怎样的权限,早已被定义好。

(2)批量调整权限

举例:有时公司上新业务模块,管理员要授权某一属性的用户查看该模块数据。比如公司新上直播功能,需要运营组可以操作直播后台,此时管理员只需要修改「运营」这个角色的权限即可修改所有运营组成员的账号权限。

引入用户组的概念

我们依旧拿上面表格案例举例,虽然前面我们应用的 RBAC 权限模型的概念,但是对于大量用户拥有相同权限的用户,我们同样的也需要对每个用户设置对应的角色,如果一个部门上万人,那么我们就需要给这个部门上万人分别设置角色,而这上万其实是具有相同的权限的,如果直接采用基础的 RBAC 权限模型的话,那么面对这样的情况,无疑也是具有一个庞大的重复的工作量,并且也不利于后期用户变更的维护管理,那么针对相同用户具有相同的权限的情况,我们便可以引入用户组的概念。

什么是用户组呢?用户组:把具有相同角色的用户进行分类。

上面我们的数据表格案例中的用户 1、用户 3、用户 5、用户 8 具有相同的角色 A,用户 2、用户 6、用户 7 也拥有相同的角色 B,那么我们就可以将这些具有相同角色的用户建立用户组的关系,拿上面的案例,我们分别对相同角色的用户建立组关系,如下:

  • 用户 1、用户 3、用户 5、用户 8→建立用户组1
  • 用户 2、用户 6、用户 7→建立用户组2

因为用户 4 只有一个用户,所以直接还是单独建立用户与角色的关系,不需要建立用户组,尽管只有一个用户也是可以建立用户组的关系,这样有利于后期其他用户与用于 4 具有相同的角色时,就可以直接将其他用户添加到这个用户组下即可,根据业务的实际情况而选择适合的方案即可。

通过案例表格的变化我们就可以直观的看出权限设置变得清晰简洁了,**通过用户组赋予角色,可以减少大量的重复的工作,**我们常见的企业组织、部门下经常会出现不同用户具有相同角色的情况,所以采用用户组的方式,便可以很好的解决这个问题,给具有相同权限的用户建立用户组,将用户组关联到对应的角色下,此用户组就拥有了此角色下的所有权限,而用户是属于用户组的,所以用户组下的所有用户也就同样的拥有了此角色下的所有权限。一个用户可以属于多个用户组,一个用户组也可以包括多个用户,所以用户与用户组是多对多的关系。

引入权限组的概念

权限组与用户组的原理差不多,是将一些相对固定的功能或者权限建立组的关系,然后再给此权限组赋予角色,目前我所接触的 B 端项目中使用权限组的概念的比较少,可简单的看一下关系图

权限组, 类似子菜单的父级菜单

功能权限和数据权限

B 端系统中一般产品的权限由页面、操作和数据构成。页面与操作相互关联,必须拥有页面权限,才能分配该页面下对应的操作权限,数据可被增删改查。所以将权限管理分为功能权限管理数据权限管理

功能权限管理:指的是用户可看到哪些模块,能操作哪些按钮,因为企业中的用户拥有不同的角色,拥有的职责也是不同的。

数据权限管理:指的是用户可看到哪些模块的哪些数据。

例如:一个系统中包含多个权责清单(清单 1、清单 2、清单 3),系统管理员能对整个系统操作维护,也就可以对系统中的所有清单进行操作(增、删、改、查);假如分配给总部权责管理员的是清单 1,那么他将只能对清单 1 进行操作(增、改、查);普通用户也许只有查看数据的权限,没有数据维操作的权限(查),这里的操作是系统中所有可点击的按钮权限操作,列举的增删改查只是最常见的几种操作而已。

实战案例总结

整个权限系统设计就是定义各个节点和节点间关系的过程。

节点包括:

用户;

用户组;

角色;

角色组;

权限(页面、操作、数据);

权限组(页面、操作、数据);

关系包括:

是/否关系;

继承关系;

限制关系(互斥、范围限制、边界限制、字段限制……);

……

梳理清楚所有逻辑后,通过灵活定义节点和组合各节点之间的关,便能够轻松完成角色权限设计的多种解法。

我目前所做的项目是一个关于权责管理平台的 B 端系统,关于系统中的权限需求我这里简单的介绍一下,并采用上面所总结的 RBAC 权限模型对实际业务需求进行设计分析:

  1. 不同的区域管理员的权限各不相同(说明会存在不同的用户具有不同的权限,那么我们就可以采用角色对其进行规范)
  2. 大量的用户具有相同的权限(例如组织、部门等)(说明存在相同权限的用户,那么我们就可以采用用户组的概念)
  3. 级管理员拥有级人员的所有权限(说明存在继承关系)
  4. 不同用户所看到的数据和能编辑的数据不同,一些机密性的数据只允许部分人员看或者编辑(说明存在约束
  5. 会存在临时性的用户(说明需要支持新建新角色)
  6. 同一用户会存在多个角色(多角色求合集或者切换用户角色

RBAC 权限模型由三大部分构成,即用户管理角色管理权限管理。

用户管理按照企业架构或业务线架构来划分,这些结构本身比较清晰,扩展性和可读性都非常好。

角色管理一定要在深入理解业务逻辑后再来设计,一般使用各部门真实的角色作为基础,再根据业务逻辑进行扩展

权限管理是前两种管理的再加固,做太细容易太碎片,做太粗又不够安全,这里我们需要根据经验和实际情况来设计。

表结构

有了上述的权限模型,设计表结构就不难了,下面是多系统下的表结构,简单设计下,主要提供思路:

Java中的常用权限框架

  • Apache Shrio
  • Spring Security

1.用户管理

用户管理中的用户,是企业里每一位员工,他们本身就有自己的组织架构,我们可以直接使用企业部门架构或者业务线架构来作为线索,构建用户管理系统

2.角色管理

在设计系统角色时,我们应该深入理解公司架构、业务架构后,再根据需求设计角色及角色内的等级。

一般角色相对于用户来说是固定不变的,每个角色都有自己明确的权限和限制,这些权限在系统设计之处就确定了,之后也轻易不会再变动。

(1)自动获得基础角色

当员工入职到某部门时,该名员工的账号应该自动被加入该部门对应的基础角色中,并拥有对应的基础权限。这种操作是为了保证系统安全的前提下,减少了管理员大量手动操作。使新入职员工能快速使用系统,提高工作效率。

(2)临时角色与失效时间

公司业务有时需要外援来支持,他们并不属于公司员工,也只是在某个时段在公司做支持。此时我们需要设置临时角色,来应对这种可能跨多部门协作的临时员工。

如果公司安全级别较高,此类账号默认有固定失效时间,到达失效时间需再次审核才能重新开启。避免临时账号因为流程不完善,遗忘在系统中,引起安全隐患。

(3)虚拟角色

部门角色中的等级,可以授权同等级的员工拥有相同的权限,但某些员工因工作原因,需要调用角色等级之外的权限,相同等级不同员工需要使用的权限还不相同。这种超出角色等级又合理的权限授予,我们可以设置虚拟角色。这一虚拟角色可集成这一工作所需的所有权限,然后将它赋予具体的员工即可。这样即不用调整组织架构和对应的角色,也可以满足工作中特殊情况的权限需求。

(4)黑白名单

  • 白名单:某些用户自身不拥有某部门的顶级角色,但处于业务需求,需要给他角色外的高级权限,那么我们可以设计限制范围的白名单,将需要的用户添加进去即可。在安全流程中,我们仅需要对白名单设计安全流程,即可审核在白名单中的特殊用户,做到监控拥有特殊权限的用户,减少安全隐患。
  • 黑名单:比较常见的黑名单场景是某些犯了错误的员工,虽然在职,但已经不能给他们任何公司权限了。这种既不能取消角色关联,也不能完全停用账号的情况,可以设置黑名单,让此类用户可以登录账号,查看基本信息,但大多数关键权限已经被黑名单限制。

3.权限管理

权限管理一般从三个方面来做限制。页面/菜单权限,操作权限,数据权限。

(1)页面/菜单权限

对于没有权限操作的用户,直接隐藏对应的页面入口或菜单选项。这种方法简单快捷直接,对于一些安全不太敏感的权限,使用这种方式非常高效。

(2)操作权限

操作权限通常是指对同一组数据,不同的用户是否可以增删改查。对某些用户来说是只读浏览数据,对某些用户来说是可编辑的数据。

(3)数据权限

对于安全需求高的权限管理,仅从前端限制隐藏菜单,隐藏编辑按钮是不够的,还需要在数接口上做限制。如果用户试图通过非法手段编辑不属于自己权限下的数据,服务器端会识别、记录并限制访问。

在实际开发中,需要设置用户只能查看哪些部门的数据,这种情况一般称为数据权限。
例如对于销售,财务的数据,它们是非常敏感的,因此要求对数据权限进行控制, 对于基于集团性的应用系统而言,就更多需要控制好各自公司的数据了。

如设置只能看本公司、或者本部门的数据,对于特殊的领导,可能需要跨部门的数据, 因此程序不能硬编码那个领导该访问哪些数据,需要进行后台的权限和数据权限的控制。

开发参考:

http://doc.ruoyi.vip/ruoyi/document/htsc.html#%E6%95%B0%E6%8D%AE%E6%9D%83%E9%99%90%E4%BD%BF%E7%94%A8

http://doc.ruoyi.vip/ruoyi/document/htsc.html#%E6%9D%83%E9%99%90%E6%B3%A8%E8%A7%A3

更多实践细节

1.超级管理员

超级管理员是用来启动系统,配置系统的账号。这个账号应该在配置好系统,创建管理员之后被隐藏起来

超级管理员账号拥有系统中全部权限,可穿梭查看各部门数据,如果使用不恰当,是系统管理的安全隐患。

2.互斥角色如何处理

当用户已经有用的角色和即将添加的角色互相互斥时,应该在添加新角色时,提示管理员因角色互斥的原因,无法进行新角色添加。如需添加,要先撤销掉前一个角色,再添加新角色。

3.用户管理权限系统设计一定要简单清晰

在设计权限系统之处,一定要理清思路,一切从简,能不增加的多余角色和权限逻辑,就一定不要增加。因为随着公司业务的扩大,权限和角色也会随之增多,如果初期设计思路不严谨,那么权限系统会随着业务的扩大而无限混乱下去,此时再来整理权限,已经太晚了。所以初期设计就一定要条理清晰,简单明了,能避免后续非常多不必要的麻烦。

4.无权提示页

有时员工 A 会直接给员工 B 分享他当下正在操作的页面,但有可能员工 B 无权查看。此时我们应该在这里考虑添加「无权提示页」,避免粗暴的404页面让员工 B 以为是系统出错了。

参考链接:

http://www.infocomm-journal.com/txxb/CN/10.11959/j.issn.1000-436x.2015329

https://zhuanlan.zhihu.com/p/357587627

以上是关于后端产品的权限系统设计的主要内容,如果未能解决你的问题,请参考以下文章

ToB产品权限系统设计(一RBAC模型)

后台产品基本功:RBAC权限后台角色与权限设计

系统权限功能的设计

用户权限系统设计与RBAC模型

[上海][部门直招] UCloud 招聘 Golang 后端工程师 15薪

B端产品之权限设计(RBAC权限模型)