数据权限的设计与实现系列1——数据权限的设计与思考

什么是数据权限?

权限控制是一个系统的核心功能,可以分为两类,一类是功能权限,一类是数据权限。数据权限又可以进一步分为行级权限和列级权限。

功能权限,是指系统用户能进行哪些操作,通常是菜单和按钮权限,如打开订单菜单,查询订单列表,创建新订单。对于功能权限,有标准化的解决方案,也即RBAC,通过权限项、角色、用户三张主表,以及角色-权限项对应关系表和角色-用户对应关系表两张辅助表,一共5张库表即可实现功能权限的功能,系统管理员通过系统界面即可实现灵活的权限分配和维护。

数据权限,是指系统用户能看到哪些范围内的数据,是具备相应功能权限的情况下,不同用户看到的数据是不同的。
一是行级权限,例如,销售部门有张三,李四、王五三人,同为销售人员的张三和李四,仅能看到自己的订单;作为部门经理的王五,则可以查看部门下所有订单。
二是列级权限,例如,对于产品,采购人员,能看到进价,不能看到售价;销售人员能看到售价,但不能看到进价;公司的财务人员,既能看到进价,又能看到售价。

相比功能权限有标准解决方案RBAC,数据权限则没有所谓的标准方案,根源在于业务系统对于数据权限的控制需求,或者说控制维度是多种多样的,很难统一化或标准化。

开发平台或开发框架没有数据权限支撑会怎么样?

常见的解决方案实际就是硬编码,具体又分为两种。
一是拆分功能页面,即根据不同数据权限用户,通过复制拷贝的方式,增加多个类似的菜单,再通过功能权限配置来给不同用户设置不同的菜单,从而实现数据权限的控制;
二是共用功能页面,内部通过功能逻辑来区分不同的用户,写一些if else的逻辑分支出来,根据不同的维度来实现。

以上硬编码的方式,无论哪一种,都无法解决灵活性的问题,系统需求变更或新增,不得不调整编码,对应的开发成本和运维成本都比较高,优点是技术难度低,实现简单。

数据权限的控制维度有哪些?

虽然业务系统对于数据权限的控制需求,或者说控制维度是多种多样的,很难标准化,但是还是有一些常用的。

首先,组织机构是最常见,使用频率最高的一个的控制维度。对于一个集团公司,北京分公司与上海分公司,业务数据在公司范围内可见;公司内部不同部门,如采购部门和销售部门,业务数据在部门内范围内可见。

其次,角色也是经常会用到的,用于跨组织机构或没有系统内部的数据从属关系,例如,公司的几个高管,每人分管几个部门,某个高管,跟分管的部门之间从系统看是没有关联的,但客观又存在业务上的需要,高管能看到自己分管的部门数据。

再次,是与当前用户相关,如要求只有发帖人才能修改帖子内容。

最后,就是跟业务实体的具体属性相关了,例如,业务类型是采购还是销售,配送方式是自提还是送到,合同金额超过100万等。

控制维度是否需要组合?

上面说过,控制维度是多种多样的,常见的几个控制维度是组织机构、角色、人员相关,那么,实际需求是否存在多控制维度的组合呢?

举个常见的典型数据权限需求例子,对于查看每月耗电量的功能
需求场景1:要求各部门经理只能查看自己部门的数据。
这实际是两个控制维度的组合,即要求角色是部门经理,且耗电量的数据归属的部门与当前用户部门相同。对于这个业务场景,如果配合功能权限,是否可以简化为一个控制维度?即查看每月耗电量这个功能菜单,只分配给部门经理这个角色,那么数据权限这边只需要控制耗电量的数据归属的部门与当前用户部门相同。

需求场景2:某些部门所有人,都可以查看自己部门每月耗电量,但不能查看别的部门的。
注意,这里说的不是所有人,所有人的处理方式相对简单,功能权限不控制,只需要附加耗电量的数据归属的部门与当前用户部门相同即可。这里说的是某些部门,例如生产部门,不包括像人力资源在内的职能部门。
这种情况下,毫无疑问,控制耗电量的数据归属的部门与当前用户部门相同是必须的。但这还不够,因为是要求某些部门的人员,而不是所有人,这时候有两种方案,一是通过角色,即新建一个角色,将这些生产部门的人都加入到角色里,给该角色赋予功能权限;二则是通过部门来直接控制数据权限。
这两种方案对比,通过角色来控制有明显的弊端,一是需要进行初始配置,新建一个角色,以及将相关人员都加入到这个角色里,初始化比较繁琐;二是当人员发生变动时,例如新入职的员工,或者人员在生产部门和职能部门之间调动,如不及时维护角色和人员的关系,都会发生访问异常问题;三是随着系统权限需求的增多,需要增加的角色也会越来越多,容易形成角色泛滥的情况,难以有效管理。而通过部门来控制数据权限,则不存在上述几个问题。
这个需求场景也论证了,只通过角色这个单一维度去进行数据权限的控制,是不合理和存在问题的。

需求场景3:高管能查看分管的部门每月耗电量数据
首先,通过类似场景1,使用角色来控制功能权限来减少一个控制维度的方式就不行了,而是必须采用角色+组织机构组合模式,即两条数据规则的或组合:
角色=部门经理且数据归属的部门与当前用户部门相同
角色=研发高管且数据归属的部门 in{研发高管分管的部门列表}

进一步深入考虑,如果有5个高管,每名高管分管3-5个部门,按照上面方式处理,最后会拼成一个复杂的sql语句给执行层,一方面,肯定会影响系统执行效率与性能;另一方面从整个系统层面而言,每个业务实体,都需要给高管分配一遍,也相当繁琐,同样不合理。

这种情况,应该换一种解决思路,即按照分管部门,再虚拟出一个上级部门来,依旧按照组织机构来管理数据权限。

如果只通过角色来控制数据权限是否可行?

既然功能权限是基于角色的,那么数据权限是不是也可以这么做呢?这么做的一个显著好处是,使系统管理员可以在角色管理界面统一设置功能权限与数据权限。但深入考虑下,这么做是有问题的。首先,本来数据权限的控制是多维度,常见的需要根据组织机构、角色、用户进行控制,如基于角色,则相当于丧失了其他控制维度,某些数据权限控制需求是难以实现的。

例如,开发了一个功能,查看每月耗电量,要求各部门经理只能查看自己部门的数据,这种情况下,菜单肯定是同一个,如果不能按组织机构去进行数据权限控制,而是基于角色,会发生什么问题呢?这时候,不得不建立大量的角色,每个部门的部门经理都要建立一个单独的角色,如采购部经理,销售部经理,会发生角色爆炸问题,给系统的初始赋权和运维带来大量的工作。

好的数据权限设计要考虑哪些因素?

一个好的功能,需要综合考虑各方面:
满足需求:首先得满足需求,这点是最重要的,业务上要求进行数据权限控制,系统实现不了,或者无法控制到对应的粒度,是有问题的。
用户友好:这里实际是包含两部分,一是对系统管理员友好;即初始化、运维方便,像上面说的,使用角色一个维度,将数据权限变相转换为了功能权限控制,造成角色爆炸,实际对用户是不友好的。二是对系统开发人员友好,即数据权限控制,最好是对开发人员透明的,无感的,如果技术上做不到,可以要求遵循一些简单的规则或处理,如要求库表中必须有创建人、创建部门等用于确定数据的归属(数据归属是数据权限控制的基础),添加权限注解等。
性能可接受:进行数据权限控制,不能过度消耗性能,引发系统执行缓慢。

数据权限控制的最小单位是什么?

业务实体对象还是具体功能操作?
如为业务实体对象整体控制,则无法满足部分更小颗粒度的权限控制需求,例如,只允许查看某些数据而不允许修改。
如控制到具体功能,系统维护是否会过于繁琐?例如,大多数情况下,允许用户对某些数据既可以查看,又可以修改。
实际情况而言,前者的场景占大多数,后者有需求,有两种处理方案,一是若是很明确的业务逻辑规则,如只允许发帖的本人对帖子编辑修改,则可以在程序中固化这种逻辑;二是系统不做处理,从管理上去约束,这种系统不管控的方式虽然不太好,但考虑到企业应用中,正常情况下是不会有人去乱改不归自己负责的数据,因为有日志,能追溯到人。

此外,实际对数据权限的控制,可以抽象成数据层面的查询、修改、删除,注意,这里没有新增,新增属于功能权限的管理范畴,数据是新增后产生的,新增前数据都不存在,谈不上数据权限管理。并且,实际的需求,高度集中在查询这个层面,修改和删除往往是明确的业务逻辑规则,可以固化在业务逻辑中。

开源平台资料

平台名称:一二三开发平台
简介: 企业级通用开发平台
设计资料:csdn专栏
开源地址:Gitee
开源协议:MIT
如果您在阅读本文时获得了帮助或受到了启发,希望您能够喜欢并收藏这篇文章,为它点赞~
请在评论区与我分享您的想法和心得,一起交流学习,不断进步,遇见更加优秀的自己!

你可能感兴趣的:(#,数据权限,数据权限,系统设计,RBAC,行级权限,权限控制)