权限设计的杂谈
这篇文章的定位,不是宣传某个框架,仅仅之是梳理一下有关权限方面的一些想法和最近项目中的一些探索过程。
咱们主要想解决一下问题。前端
- 什么是权限,程序员理解的权限和客户所理解的权限是否是一致的。
- 权限的划分原则,权限究竟是根据什么原则进行组合的。
- 角色是用户与权限之间的必要的关系吗?角色到底承接了什么做用。
- 如何进行合理的表设计。
- 安全框架。
1.什么是权限
在不少与开发者也好,与客户也好,沟通的过程当中咱们不少次提到了权限,可是权限具体的含义每一个人理解的含义都不明确,这样很容易形成双方信息不对称,有的人就只是把权限理解成某个页面的是否可访问,可是有的人却理解成其余的东西。因此咱们要完全的定义一下权限是什么。
权限究竟是名词属性仍是动词属性,仍是名词、动词属性均包含,这对于权限的含义很重要。若是是名词属性的话,那么它应该是有具体的指代物;若是是动词,则应该具备行为表示。java
- 权限的名词属性:api接口、页面、功能点。
- 权限的动词属性:可操做、不可操做。
那么咱们如今来看,其实权限是名词、动词属性,它必定是表达了两层含义。即控制的对象、操做。程序员
- 例如:权限A表示页面A的可访问。
- 例如:权限B表示页面B可访问且页面内的功能b不可以使用
- 例如:权限C表示接口C不可调用。
- 例如:权限D表示页面D可访问,且接口D可访问。
那么进一步的说明,权限能够表示单个控制的对象的操做集合,也能够表示多个控制的对象的操做集合。而这二者的取舍则是有设计人员决定的。数据库

一句话总结权限的含义:what(若干元素)进行how(若干操做)
2.权限的划分原则
咱们了解了权限的具体含义以后,接下来就是用的问题,咱们该如何去使用权限,如何将系统中的操做元素进行一个组合,这个我借鉴网上的一篇文章来解释。划分原则能够按照“最小特权原则”和“数据抽象原则”。
- 我先举一个反例,我把系统中全部的元素和操做都组合成一个权限。一个用户拥有这个权限就至关拥有了系统全部的功能,实际上这确定是不行的,用户在一套系统中必定有他不容许操做的内容,哪怕是超级管理员也可能会有不能操做的元素,那么最大化权限则是行不通,由于不符合常理。
- 据此,咱们就把权限再进行一个拆分,按照业务模块进行拆分,可是这实际上也是不行的。就好比系统中的财务模块,假定模块中含有报销页面和申报页面,若是按照模块进行拆分,那么确定有用户同时包含了两个互斥功能。
- 根据1和2,咱们须要按照最小化进行权限划分。可是这个也是值得商榷的,由于不一样系统,最小的权限划分对于提供的功能来讲,划分的角度也是不一样的。
- “最小特权划分”从某个程度上来讲决定了控制的对象 ,而数据抽象原则是是决定了操做。
- 数据抽象从字面的意思来看,其实很难理解究竟是什么意思。一般咱们口头上说最多的是CRUD增删查改,这实际上就是数据抽象的一种,咱们能够理解成元素操做许可权的意思。
- 可是CRUD并非数据抽象的所有,增删查改用于单实体,基本是没问题的,可是在构建关系上,实际上是不够用的,例如任免某个经理管辖某个部门,从业务表面而言它修改了经理的管辖范围。可是从代码底层构建上来讲,它属于在经理和部门间新增了一道关系,因此根据需求咱们须要再额外的增长一类许可权“任免许可”,这一类型的扩展则须要根据系统实际的业务状况进行划分。
“最小特权”和“数据抽象”分别决定了权限中
控制的对象和
操做,可是这里面还差了一个角度,则是现阶段很是广泛的先后端分离的权限划分的问题。
- 先后端分离下的服务端,本质而言只是提供接口的或者rpc服务等其余资源服务的服务提供方。
- 服务端能提供的权限的鉴权机制的对象:接口服务(api或者其余形式的服务)不包含前端的页面或页面中的功能点。
- 前端或移动端的页面元素的控制和鉴权实质上不禁服务端控制。
- 服务端能够单独的控制服务的权限。
- 服务端的服务对象是前端、移动端、第三方客户端,提供的服务是接口服务。
在先后端已经分离的状况下,服务端对于前端而言只是接口的提供者,但无权干涉前端页面的展现,服务端对于前端而言,能提供的是仅鉴权服务的接口而已,可是页面的构成,页面的栏目菜单或页面内的功能点的构成均由前端单独完成的。
- 前端的鉴权包含页面的可访问,和页面上的某项功能按钮是否能够操做。
- 前端和移动端的服务对象是用户,提供的服务是可视化的页面。

先后端的服务对象的责任划分清晰以后,咱们就不会混杂权限的归属的问题,在过去先后端没分离的状况下,页面自己就是服务端的一体,就没有这方面的问题。虽然分清楚了各端本质提供的服务的状况,可是先后端分离的权限划分中仍有新的问题。
- 由于服务端和前端的鉴权对象不一致,服务端只能鉴权到api接口,那么是否将api接口和前端的页面乃至页面功能点进行数据库表与表层面的绑定关系。
- 若是进行了进行了表与表之间的绑定关系,那么整个权限系统的维护量,是否能在能承受范围以内。
- 若是不进行表与表之间的绑定关系,前端页面在操做功能的时候,服务端如何鉴权页面调用的api接口是否在用户可操做的权限以内?
其实上面的问题则须要一个取舍,要么增长运维成本严格控制前端调用api接口的关系,偏重服务端的接口服务鉴权。要么是给api接口和前端页面及功能点再提供一个通性的逻辑判断处理,如:页面及调用的功能点属于某个业务模块的操做许可,而页面触发的接口也恰好是这个业务模块的操做许可,那么鉴权经过,不然鉴权失败。这种就是属于侧重前端对于用户的控制,弱化了接口级的控制。
3.角色与权限的关系
经过1,2的描述,基本肯定了权限的定义和划分一个权限的通用法则。用户在系统中最终是经过权限来使用各类功能点,是否有必要在用户和权限中间再额外的附加一个关系。在咱们如今的权限设计中,是增长了这样一层关系的,就是角色。
- 减小操做层面的重复性。角色其实就是一组权限的集合,是权限集合的更高级抽象,为了便于运维和实际管理,经过角色的赋予,替代了权限赋予用户的繁琐性,在一套系统中,广泛状况都是权限的数量多于角色的数量。
- 权限是控制对象和操做集合,它自己不存在任何状态,可是在赋予在用户身上则拥有了状态,好比权限A中容许用户访问页面A,权限B容许用户访问页面B,权限D运行用户访问B页面,可是不容许访问A页面。那么这层关系的维护在角色层面的话,会更加清晰,也就是说自己角色具备权限集合组装的策略问题,对于互斥的权限有不一样的方案处理。(权限中没有某个操做和权限中禁止某个操做,是两个不一样的角度,不能混为一谈)
- 由于权限的可能存在互斥性,在实际业务中也会引起角色的互斥性,举一个现实中的案例来解释互斥性:张三是软件部的负责人但由于工做的特殊性也一样隶属于业务部的普通员工,咱们设定负责人是能够要求人事部门给本部门进行招聘的,在实际的状况中,张三能给软件部招聘新员工,可是不能给业务部招聘员工。咱们把这个案例运用在系统中,张三则是拥有负责人和普通员工两个角色,可是招聘的功能若是不加以控制,则会发生张三给业务部招人的结果。因而为了解决角色的这类问题,引入了职责划分的方案。
- 职责划分分为:静态、动态。所谓静态职责划分则是在角色建立之初就已经肯定了角色的职责内容。动态职责划分是系统运行过程当中对用户已有的角色进行控制,例如:某些角色不能共存在用户身上(互斥)、角色或角色的分配数量限定(控制用量)、角色与角色同时只能激活一个进行使用(时刻惟一)。
引入角色的概念后,实际上这已是一个比较完整的RBAC的权限设计的模型了。

4.数据表的设计思路
根据3的结论,实质上已经有了一个基础的表设计的雏形。在这里就有一些值得注意的点。后端
- (1)问:权限表是否有必要存在?
- (1)答:这个要结合系统的实际使用场景进行考虑,若是系统中的权限的对象很单一,好比只有页面,或者只有api接口的话,其实权限表无关紧要。增长权限表反而会致使初始化项目权限的工做量增长。可是若系统中的权限对象是多个,那么权限表的存在就有了更深层次的意义。在权限对象是多个的状况,权限表的存在就是为了更好更抽象的组合“最小特权”及“责任划分”的操做对象。同时,一旦系统中的操做对象增长了,只须要给权限表增长一个对象表和关系表就能够了。这样易于扩展。
- (2)问:api接口和页面其实是没有关系的,可是在鉴权活动是有关系的,页面若和api没有一点绑定联系的话,服务端接口调用的时候则要么拦截掉全部指定的接口(页面和api接口没绑定的话,则页面的接口调用都不能成功),服务端接口彻底不拦截接口,也会不安全,可是api接口和页面功能在表结构层面的绑定会产生运维的大量工做成本,如何更好的设计。
- (2)答:在权限如何划分中已经提过了这一点,在表结构中,咱们能够增长一张业务模块表和操做表(也能够在数据字典表中增长这两类数据),咱们能够在页面和功能点钟 绑定业务模块和操做表关系,在api接口的代码层面去绑定业务模块和操做,在逻辑上绑定关系,解耦表结构之间的关系,那么能够在必定程度上解决这一点,这样作只会出现一种问题,那就是用户访问页面的时候可调用的api接口会比实际可调用的接口数要多,可是前端权限管理会隐藏功能点,这样就在可视化的程度上解决了这个问题。
5.安全框架
因为咱们是基于RBAC的权限设计,现行java框架下最多见的就是shiro和Spring Security 。这两个就是仁者见仁智者见智了,我二者都实用过。仅建议使用shiro的话,能够更好的理解RBAC的设计思路,Spring Security 也是个不错的框架,可是它涉及到的概念太多,并不利于初学者去了解最基本的权限设计。我在这只在学习的角度上去比较这两个框架,并无再其余领域去作比较,也不去比较。
引用的文章
[权限系统与RBAC模型概述[绝对经典]](https://blog.csdn.net/yangwen...api