# 主流权限系统的设计

2023年6月28日25分钟阅读

- FormalSciences/ComputerScience
- ComputerSecurity/UserSecurity

## 认证

认证（Identification） 是指根据声明者所特有的识别信息，确认声明者的身份。你需要用身份证证明你自己是你自己。比如我们常见的认证技术：身份证、用户名和密码、用户手机：手机短信、手机二维码扫描、手势密码、电子邮箱、指纹、语音、眼睛虹膜、大数据识别等等

## 授权

授权（Authorization）在信息安全领域是指资源所有者委派执行者，赋予执行者指定范围的资源操作权限，以便对资源的相关操作。

- 现实生活领域：银行卡（由银行派发）、门禁卡（由物业管理处派发）、钥匙（由房东派发），这些都是现实生活中授权的实现方式。

- 互联网领域： Web 服务器的 Session 机制、Web 浏览器的 Cookie 机制、颁发授权令牌（Token）等都是一个授权的机制。

## 鉴权

鉴权（Authentication）在信息安全领域是指对于一个声明者所声明的身份权利，对其所声明的真实性进行鉴别确认的过程。若从授权出发，则会更加容易理解鉴权。授权和鉴权是两个上下游相匹配的关系：先授权，后鉴权。

- 现实生活领域： 门禁卡需要通过门禁卡识别器，银行卡需要通过银行卡识别器；

- 互联网领域： 校验 Session / Cookie / Token 的合法性和有效性

鉴权是一个承上启下的一个环节，上游它接受授权的输出，校验其真实性后，然后获取权限（Permission），这个将会为下一步的权限控制做好准备。

## 权限控制

权限控制（Access/Permission Control） 将可执行的操作定义为权限列表，然后判断操作是否允许/禁止。对于权限控制，可以分为两部分进行理解：一个是权限，另一个是控制。权限是抽象的逻辑概念，而控制是具体的实现方式。

- 现实生活领域： 以门禁卡的权限实现为例，一个门禁卡，拥有开公司所有的门的权限；一个门禁卡，拥有管理员角色的权限，因而可以开公司所有的门。

- 互联网领域： 通过 Web 后端服务，来控制接口访问，允许或拒绝访问请求。

## 认证、授权、鉴权和权限控制的关系？

认证、授权、鉴权和权限控制，这四个环节是一个前后依次发生、上下游的关系；需要说明的是，这四个环节在有些时候会同时发生。 例如在下面的几个场景：

- 使用门禁卡开门： 认证、授权、鉴权、权限控制四个环节一气呵成，在瞬间同时发生。

- 用户的网站登录： 用户在使用用户名和密码进行登录时，认证和授权两个环节一同完成，而鉴权和权限控制则发生在后续的请求访问中，比如在选购物品或支付时。

权限管控可以通俗的理解为权力限制，即不同的人由于拥有不同权力，他所看到的、能使用的可能不一样。对应到一个应用系统，其实就是一个用户可能拥有不同的数据权限（看到的）和操作权限（使用的）。

## 权限模型

主流的权限模型主要分为以下五种：

- ACL 模型：访问控制列表
- DAC 模型：自主访问控制
- MAC 模型：强制访问控制
- ABAC 模型：基于属性的访问控制
- RBAC 模型：基于角色的权限访问控制

### ACL 模型：访问控制列表

Access Control List，ACL 是最早的、最基本的一种访问控制机制，是基于客体进行控制的模型，在其他模型中也有 ACL 的身影。为了解决相同权限的用户挨个配置的问题，后来也采用了用户组的方式。

原理：每一个客体都有一个列表，列表中记录的是哪些主体可以对这个客体做哪些行为，非常简单。

例如：当用户 A 要对一篇文章进行编辑时，ACL 会先检查一下文章编辑功能的控制列表中有没有用户 A，有就可以编辑，无则不能编辑。再例如：不同等级的会员在产品中可使用的功能范围不同。

缺点：当主体的数量较多时，配置和维护工作就会成本大、易出错。

### DAC 模型：自主访问控制

Discretionary Access Control，DAC 是 ACL 的一种拓展。

原理：在 ACL 模型的基础上，允许主体可以将自己拥有的权限自主地授予其他主体，所以权限可以任意传递。

例如：常见于文件系统，LINUX，UNIX、WindowsNT 版本的操作系统都提供 DAC 的支持。

缺点：对权限控制比较分散，例如无法简单地将一组文件设置统一的权限开放给指定的一群用户。主体的权限太大，无意间就可能泄露信息。

### MAC 模型：强制访问控制

Mandatory Access Control，MAC 模型中主要的是双向验证机制。常见于机密机构或者其他等级观念强烈的行业，如军用和市政安全领域的软件。

原理：主体有一个权限标识，客体也有一个权限标识，而主体能否对该客体进行操作取决于双方的权限标识的关系。

例如：将军分为上将 > 中将 > 少将，军事文件保密等级分为绝密 > 机密 > 秘密，规定不同军衔仅能访问不同保密等级的文件，如少将只能访问秘密文件；当某一账号访问某一文件时，系统会验证账号的军衔，也验证文件的保密等级，当军衔和保密等级相对应时才可以访问。

缺点：控制太严格，实现工作量大，缺乏灵活性。

### ABAC 模型：基于属性的访问控制

Attribute-Based Access Control，能很好地解决 RBAC 的缺点，在新增资源时容易维护。

原理：通过动态计算一个或一组属性是否满足某种机制来授权，是一种很灵活的权限模型，可以按需实现不同颗粒度的权限控制。

属性通常有四类：

1. 主体属性，如用户年龄、性别等；
2. 客体属性，如一篇文章等；
3. 环境属性，即空间限制、时间限制、频度限制；
4. 操作属性，即行为类型，如读写、只读等。

例如：早上 9:00，11:00 期间 A、B 两个部门一起以考生的身份考试，下午 14:00，17:00 期间 A、B 两个部门相互阅卷。

缺点：规则复杂，不易看出主体与客体之间的关系，实现非常难，现在应用的很少。

### RBAC 基于角色的权限访问控制

Role-Based Access Control，核心在于用户只和角色关联，而角色代表对了权限，是一系列权限的集合。

RBAC 三要素：

1. 用户：系统中所有的账户
2. 角色：一系列权限的集合（如：管理员，开发者，审计管理员等）
3. 权限：菜单，按钮，数据的增删改查等详细权限。

在 **RBAC **中，权限与角色相关联，用户通过成为适当角色的成员而得到这些角色的权限。

角色是为了完成各种工作而创造，用户则依据它的责任和资格来被指派相应的角色，用户可以很容易地从一个角色被指派到另一个角色。

角色可依新的需求和系统的合并而赋予新的权限，而权限也可根据需要而从某角色中回收。角色与角色的关系同样也存在继承关系防止越权。

优点：便于角色划分，更灵活的授权管理；最小颗粒度授权；

## RBAC 的深度拓展

RBAC 模型可以分为：RBAC0、RBAC1、RBAC2、RBAC3 四个阶段，一般公司使用 RBAC0 的模型就可以。另外，RBAC0 相当于底层逻辑，后三者都是在 RBAC0 模型上的拔高。

我先简单介绍下这四个 RBAC 模型：

### 1. RBAC0 模型

用户和角色、角色和权限多对多关系。

简单来说就是一个用户拥有多个角色，一个角色可以被多个用户拥有，这是用户和角色的多对多关系；同样的，角色和权限也是如此。

RBAC0 模型如下图：没有画太多线，但是已经能够看出多对多关系。

### 2. RBAC1 模型

相对于 RBAC0 模型，增加了角色分级的逻辑，类似于树形结构，下一节点继承上一节点的所有权限，如 role1 根节点下有 role1.1 和 role1.2 两个子节点

角色分级的逻辑可以有效的规范角色创建（主要得益于权限继承逻辑），我之前做过 BD 工具（类 CRM ），BD 之间就有分级（经理、主管、专员），如果采用 RBAC0 模型做权限系统，我可能需要为经理、主管、专员分别创建一个角色（角色之间权限无继承性），极有可能出现一个问题，由于权限配置错误，主管拥有经理都没有权限。

而 RBAC1 模型就很好解决了这个问题，创建完经理角色并配置好权限后，主管角色的权限继承经理角色的权限，并且支持针对性删减主管权限。

### 3. RBAC2 模型

基于 RBAC0 模型，对角色增加了更多约束条件。

如角色互斥，比较经典的案例是财务系统中出纳不得兼管稽核，那么在赋予财务系统操作人员角色时，同一个操作员不能同时拥有出纳和稽核两个角色。

如角色数量限制，例如：一个角色专门为公司 CEO 创建的，最后发现公司有 10 个人拥有 CEO 角色，一个公司有 10 个 CEO ？这就是对角色数量的限制，它指的是有多少用户能拥有这个角色。

RBAC2 模型主要是为了增加角色赋予的限制条件，这也符合权限系统的目标：权责明确，系统使用安全、保密。

### 4. RBAC3 模型

同样是基于 RBAC0 模型，但是综合了 RBAC1 和 RBAC2 的所有特点

这里就不在多描述，读者返回去看 RBAC1 和 RBAC2 模型的描述即可。

## RBAC 权限管理的在实际系统中的应用

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

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

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

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

### 1. 用户管理

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

需要特殊注意：实际业务中的组织架构可能与企业部门架构、业务线架构不同，需要考虑数据共享机制，一般的做法为授权某个人、某个角色组共享某个组织层级的某个对象组数据。

### 2. 角色管理

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

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

#### 1. 自动获得基础角色

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

#### 2. 临时角色与失效时间

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

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

#### 3. 虚拟角色

部门角色中的等级，可以授权同等级的员工拥有相同的权限，但某些员工因工作原因，需要调用角色等级之外的权限，相同等级不同员工需要使用的权限还不相同。

这种超出角色等级又合理的权限授予，我们可以设置虚拟角色。这一虚拟角色可集成这一工作所需的所有权限，然后将它赋予具体的员工即可。这样即不用调整组织架构和对应的角色，也可以满足工作中特殊情况的权限需求。

#### 4. 黑白名单

白名单：某些用户自身不拥有某部门的顶级角色，但处于业务需求，需要给他角色外的高级权限，那么我们可以设计限制范围的白名单，将需要的用户添加进去即可。

在安全流程中，我们仅需要对白名单设计安全流程，即可审核在白名单中的特殊用户，做到监控拥有特殊权限的用户，减少安全隐患。

黑名单：比较常见的黑名单场景是某些犯了错误的员工，虽然在职，但已经不能给他们任何公司权限了。这种既不能取消角色关联，也不能完全停用账号的情况，可以设置黑名单，让此类用户可以登录账号，查看基本信息，但大多数关键权限已经被黑名单限制。

### 3. 权限管理

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

#### 1. 页面/菜单权限

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

#### 2. 操作权限

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

#### 3. 数据权限

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

#### 4. 数据权限如何管控

数据权限可以分为行权限和列权限。行权限控制：看多少条数据。列权限控制：看一条数据的多少个字段。

简单系统中可以通过组织架构来管控行权限，按照角色来配置列权限，但是遇到复杂情况，组织架构是承载不了复杂行权限管控，角色也更不能承载列的特殊化展示。

目前行业的做法是提供行列级数据权规则配置，把规则当成类似权限点配置赋予某个角色或者某个用户。

### 唯一登录

唯一登录是指禁止多人同时登录同一账号，后者的登录行为，会导致前者掉线。

通俗点讲就是：A 账号在 A 电脑上登录后，A 账号此时又用 B 电脑再次登录，则 A 电脑请求页面时，提示“重新登录”的信息，并跳转到登录页面

#### 唯一登录流程图

#### 唯一登录步骤详解

#### 用户 - 客户端 A 操作

1. 输入账号请求登录接口。
2. 后端生成对应 Token 并且返回给客户端 A，并且在服务端保存一个登录状态。
3. 客户端 A 保存 Token，并且每次请求都在 header 头中携带对应的 Token。

#### 用户 - 客户端 B 操作

1. 输入账号请求登录接口。
2. ……

用户在客户端 B 上开始登录操作时，我们会发现，步骤和在客户端 A 上面的操作几乎是一致的。只是后端在生成新的 Token 时，要先验证登录状态，然后再生成对应新的 Token；

## 用户管理系统权限设计中的更多实践细节

### 1. 超级管理员

超级管理员是用来启动系统，配置系统的账号。这个账号应该在配置好系统，创建管理员之后被隐藏起来。超级管理员账号拥有系统中全部权限，可穿梭查看各部门数据，如果使用不恰当，是系统管理的安全隐患。

### 2. 互斥角色如何处理

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

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

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

### 4. 无权提示页

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