产品化思维之权限管理

文中内容写于2014-5

——-----------------------

权限管理是每个软件系统无法绕过的一个问题,或大或小的系统都要考虑。之所以要考虑,是应为不同的人,属于不同的岗位,他所具有的岗位职责是不同的,体现到软件里将,就是可以使用的功能是不一样的,而且根据企业内控制度,有些岗位之间的职责是互斥的,比如财务上,会计和出纳不能是同一个人。另外,处于企业数据安全和商业机密考虑,也希望不同岗位的人看到的数据也有要求,有些数据有些人能看到,有些人就不能看到。所有这些,必须通过权限控制来实现。

1. 用户权限包括功能权限和数据权限。

功能权限是指能否调用某个程序功能,数据权限是指,能否对某个数据做什么。

功能权限和数据权限是紧密相关的。其实数据权限就包括功能权限(做什么)。之所以把数据权限和功能权限分来,主要是习惯使然,或者这样说比较容易说一些。

2.功能权限有两个层面。

什么叫功能。从根上讲功能就是执行程序的一段代码,而这段代码实现一个业务目标,比如创建一个订单,修改一个订单,给客户付款,查询某些数据等等。这些功能都要有个调用的入口,入口要么来自前台界面,要么来自后台程序。有时候一个界面一般也体现为一个功能,一个菜单项有对应一个界面,因此功能的业务模型是下面的形式:

菜单1-->1界面1-->M功能。上面的数字是对应关系。m:n,一个菜单对应一个主界面,一个主界面对应多个功能点。

一般系统实现功能权限是靠控制菜单来实现的,分配权限时,按照菜单进行分配,登录系统后,只显示有权限执行的菜单,没有权限的菜单隐藏掉,从而达到功能权限的控制的目的。这是最初级的功能权限控制。一般实现到这个程度也够用了。

但是这种控制局限性是显然的,如果在一个菜单功能管理调用另外一个菜单功能点的话,就没法控制了,所有有些系统做了改进,分配功能权限不仅仅是看菜单了,而是对所有功能号,统一进行功能权限分配,在调用的 时候检查是否可以执行,这样就吧这条路给封死了,进了一步。

这样,如果将功能里的每个子菜单、甚至按钮都控制i起来,这样,功能权限的控制就比较严谨和完整了。

这样,分配功能权限时的界面就复杂了,备选功能就不仅仅是菜单项了,还要包括每个界面中的每个字菜单和按钮。

其实我们从更抽象的层次来考虑这个问题,如果我们吧所有的可以被用户调用的功能都整理出来,就能控制到所有的功能权限了。这样无论是从菜单来调用,还是在界面中通过按钮来调用,还是直接通过代码调用,无论是前台调用,还是后台调用,都通过同一个入口去调用,在这个入口进行权限检查, 就都能控制住了。

这里有个问题:菜单入口对应的是什么?是不是控制的最小粒度?一个菜单界面的主题功能是什么?

我们思考下界面和后台调用的关系:

我们以创建订单为例。从给用户的操作界面来看,创建订单有两种模式:

M1:提供一个界面,由用户录入一些必要的数据,调用后台创建订单。

M2:通过API的方式,提交订单数据,调用创建订单的后台功能,在后台数据库中的订单表中插入订单这条记录,并执行一些相关的数据变更。

其实,方法M1就是调用的M2来实现的。只不过M1提供了可视化的界面而已,一般来讲在客户端会有一个功能码(T-code),可能还会提供一个菜单,这个菜单在关联这个功能码T-CODE。这样就出来三个需要控制的东西:菜单项,事务码,功能码。我们分别称之为 M-CODE,T-CODE,F-CODE,前两个是一码事,是打开界面的两种方式(GUI方式和命令行方式),M和T的关系是:1:1,M/T和F的关系n:m。就是在一个M中,可能会调用多个F,同时一个F也会被多个M调用。

那么问题来了,我们在做系统的功能权限控制时,要控制哪个呢?都要控制,控制M是为了组织菜单,属于UI的部分,控制F是为了做到彻底控制,包括通过API调用时的控制。

这样存在一个问题:Fx之间有没有互相包含的关系,如果出现的话,如何处理?

出现的可能有两种:设计失误;确实有包含关系。如果有的话,提供要提供冲突检查。举例讲,如果 F由F1 和 F2 来实现。如果对张三分配了 F 和 F1,但是没有分配 F2,那么 F其实是执行不了的,因为他的授权是不完整的。那么,在 分配F时,要自动将F1和F2给他授权。

3.再说数据权限。

这个就不像功能权限那么简单了。数据权限还是比较复杂的。从理论上,数据权限有成熟的模型,RBAC,role-based access control,基于角色的资源访问控制模型,权限是个三元组(Ro,Re,Ac),分别是(角色,资源,操作),这个三元组返回的值要么是 true,要么是 false。

(1)首先要分析出,也可以说定义出,要控制哪些数据(要控制的数据称之为资源 resource)。更一般讲,资源的外延可以很大,比如电脑,打印机,服务器,程序组件,都可以称之为资源,都可以作为控制的对象,其实每个功能也是一个资源,如果这样说的话,功能权限和数据权限就可以统一进行管理和分配了。但是习惯上讲,还是把二者分开,但是我们后台实现可以把二者统一起来。

(2)再来看资源访问的主体,也就是谁来操作它,一般是用户。当然更抽象来讲,用户可以是个实实在在的人,比如我们一般说的最终用户,也可能是一个外部系统。无论是一个是实在的人,还是外部系统,在系统里都被称之为账号(account),都对应一个账号,这样,我们统一用账号来称呼之。其实在实际企业中,除了用户(职工外),还有个更高级别的概念,就是岗位,岗位是不指定到人的,是根据实际的业务分工,职责来定义的,某个岗位负责做那些业务,可以访问那些数据等等。比如我们熟悉的资产管理岗,财务,出纳,总经理等等都是岗位的例子。

其实岗位就是角色的另一个称呼,老外称之为role。可能还有一个单词比较接近,position。但是常用role。

一般成熟的软件,功能都是分配到角色role的。这样的优点是,将权限和用户通过角色隔离开来。

(3)三看操作类型有哪些。对通常的数据来讲,比如对产品记录,发票记录,可以有查看,修改,增加,删除的操作,再继续说,还有导出,打印的操作。

对功能资源来讲,操作就是“打开”,也可以称之为“使用、调用”。

数据权限比功能权限要复杂,复杂在哪?功能权限来讲,要分配的功能是固定的,是设计时的,一个系统开发完了,功能就那么多了,不再变了;而要控制的数据则是多变的,也就是说是运行时的,而不是设计时的。比如部门字典,商品字典,发票条数等等,在系统刚运行时是不变变化的,一般是不断增加的。数据权限分配到角色是否可行呢?想一下以下的场景,部门经理只能看到属于本部门的员工。这个权限控制如果定义到角色“部门经理”的话,应该怎么定义呢?将某个部门的所有员工制定到“部门经理”这个角色,显然是不行的,应为其他的部门也有“部门经理”这个岗位。有的说了那好,可以这样,张三是部门经理,张三肯定也有“所属部门”这个属性,那么我们可以使用“所属部门”这个宏,来实现通过部门控制数据权限的目的。这样在权限运算时,取得张三的部门,然后取得所有要访问的员工的部门,这两个部门匹配就可以了。这样是个思路,但是如果在复杂怎么办呢?比如一个部门经理如果管多个平行的部门怎么办,不如张经理既管开发部的工作,有主持服务部们的工作。如果坚持用角色来定义的话,角色的数量可能会和用户的数量差不多。比如sap就是这样处理的,分配权限(功能权限和数据权限)都是分配到角色,sap中的角色分角色(Role),通用角色(Common Role)和本地角色(Local Role),所谓通用角色是和组织结构没有关系的,而本地角色是指定到某个单位的。

所以数据权限的分配有两种,一是分配到用户,一种是分配到“本地角色”。

感兴趣的可以了解下sap中的权限模型,还是比较完备的,几乎可以满足任何需求,缺点是比较复杂。

sap权限参考:http://tech.sina.com.cn/s/2008-11-25/1107887414.shtml

我复制下来了,供各位参考,了解sap的权限控制模型。从sap的模型中,可以看出,sap是把数据权限和功能权限(tcode)统一进行管理了。至少在内部实现上是这样的。

4. 用户与角色的关系

   一个用户可以属于多个角色,就像现实中,一个人可以兼多岗一样的道理。这个没什么可讨论的。基本上是固定的模式了。

几个纠结的问题:

(1). 初入道者经常纠结一个问题,就是用户和角色的关系。记得前几年做一个系统,这个地方就犯了纠结,当时的实现是,既可以给角色分配权限,也可以给用户分配权限,然后将角色指定到用户。这样用户就具有了所属角色的所有权限+分配给他的权限的合集。当初这么做的原因是,如果一个用户属于某几个角色,但是他又想具有这些角色之外的某些功能,而感觉再新建一个角色没必要,这个角色只有一个人用。

其实这样做意义不大,除了能带来代码复杂性之外,没有任何好处,多创建一个角色又能有多麻烦。这个要说服用户接受角色的概念。即便一个角色只有一个权限,也要用权限来实现。优点是事降低代码的复杂度,使系统更稳定,也降低的使用的难度和理解的难度,这样给用户说就行。

所以分配功能权限只对角色分配就行!没必要对用户分配。这个没有什么高深的理论,经验之谈,所以直接这么定就可以了,没必要在纠结了。

以上是对权限的思考。如何做,做到什么程度,要看实际场景。是做项目,还是做产品,二者的要求是不同的。大家可以了解下,凡是完善的产品,其权限控制的实现是非常复杂的。

等有时间再结合实际的业务场景写一下具体如何实现权限控制。

原文地址:https://www.cnblogs.com/senline/p/14810697.html