RBAC模型的分析与实现

前言

本文介绍了 RBAC 的基本概念,并对其常用的几种延伸模型进行了说明,最后使用 MySQL 给出了其中一种模型的具体实现。

介绍

RBAC 全称为基于角色的访问控制模型( Role-based access control ),在该模型中,通过让权限与角色关联来实现授权,给用户分配一系列的角色来让注册用户得到这些角色对应的权限,使系统权限分配更加方便。我们在一般的大型系统开发中,几乎都要考虑权限控制的相关问题,诸如:系统资源权限、用户行为权限等,此类问题的实现通常需要数据库在设计时做出考虑,经过 IT 届各种大佬的长期实践后,总结出了较为通用的针对权限控制的 RBAC 设计模型。 RBAC 不是某种技术框架,它类似于设计模式,是当下流行的一种数据库(表)设计的思想,它能通过为用户分配角色来实现权限的分配,只要你的数据库设计满足这种思想便可说你的数据库使用的是 RBAC 模型。

分类

概述

在RBAC模型中,一般有以下组成部分:

  • 用户( User ):定义需要权限鉴别操作的主体
  • 角色( Role ):定义一批相关联权限的集合
  • 权限( Permission ):定义需要鉴别权限操作的对象
  • 用户-角色关联( User-Role ):定义用户所具有的角色
  • 角色-权限关联( Role-Permission ):定义角色所具有的权限
    https://cdn.jsdelivr.net/gh/wefantasy/FileCloud/img/20200602072659.png
    RBAC

RBAC0/基本模型

RBAC0 是最基本的模型,未做特殊要求和扩展,在该模型中,一个用户可以同时拥有多个角色,每个角色可以拥有多个权限。

https://cdn.jsdelivr.net/gh/wefantasy/FileCloud/img/20200602072901.png
RBAC0

RBAC1/继承模型

RBAC1 在 RBAC0 的基础上进行了拓展,主要变化在于增加了角色之间的继承关系(类似于 Java 类继承),子角色除了拥有自己的权限外也拥有父角色所具有的所有权限。此外 RBAC1 又分为一般继承和受限继承:一般继承关系允许角色间存在多继承;受限继承则要求角色继承关系是一个严格的树结构。总体来说这两种思想在设计上差别不大,仅在应用上有略微差别。

https://cdn.jsdelivr.net/gh/wefantasy/FileCloud/img/20200602073851.png
RBAC1

RBAC2/限制模型

在部分权限要求较为严格的系统中,会要求具有特定职责的用户不能具有职责之外的权限(角色)(责任分离),这些限制会体现在系统上层开发语言中而与数据库设计实现无关。例如:在一个公司中,经费申请部门不能拥有经费审核部门的权限。此模型中常用以下限制:

  • 互斥角色 :同一用户只能分配到一组互斥角色集合中至多一个角色。
  • 基数约束 :一个角色被分配的用户数量受限、一个用户可拥有的角色数目受限、同样一个角色对应的访问权限数目也应受限……
  • 先决条件角色 :想获得B角色必须已有A角色。
  • 运行时互斥 :在同一时刻只有一个角色生效。

RBAC3/综合模型

RBAC3 是 RBAC1 和 RBAC2 的综合,既包含角色间的继承关系,又对用户角色进行限制。

实现

以下是 RBAC1 模型的 MySQL 数据库的实现,系统ER图如下:

https://cdn.jsdelivr.net/gh/wefantasy/FileCloud/img/RBAC-ER.png
ER图

用户表

该表主要包含了基本的用户信息。

1
2
3
4
5
6
7
8
DROP TABLE IF EXISTS `admin`;
CREATE TABLE `admin`  (
  `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `username` varchar(255) NOT NULL UNIQUE,
  `password` varchar(255) NOT NULL,
  `last_login_time` datetime NULL COMMENT '最后登陆时间',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COMMENT='管理员表';

角色表

该表储存角色信息,其中pid是父级角色的ID值(用于实现角色继承)、code是角色代码(BASE_ADMINSUPER_ADMIN)、icon是前端图标,可有可无、sort用于出现多种同级角色时排序。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
  `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `pid` int(11) NOT NULL COMMENT '父级角色id',
  `code` varchar(255) NOT NULL COMMENT '角色代码',
  `icon` varchar(255) COMMENT '图标',
  `description` varchar(255) NOT NULL COMMENT '描述',
  `status` int(1) NULL DEFAULT 1 COMMENT '启用状态:0->禁用;1->启用',
  `sort` int(11) NULL DEFAULT 0 COMMENT '权重'
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COMMENT='角色表';

权限表

该表主要包含具体权限信息,其中name是权限名称(介绍)、value是权限值(识别标志)、type是权限类型(目录权限、菜单权限、按钮权限)、uri是前端资源路径(通常用于web系统中)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission`  (
  `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `name` varchar(255) NOT NULL COMMENT '名称',
  `value` varchar(255) NOT NULL COMMENT '权限值',
  `icon` varchar(255) COMMENT '图标',
  `type` int(1) DEFAULT 2 COMMENT '权限类型:0->目录;1->菜单;2->按钮(接口绑定权限)',
  `uri` varchar(1024) COMMENT '前端资源路径',
  `sort` int(11) NULL DEFAULT 0 COMMENT '权重',
  `status` int(1) NULL DEFAULT 1 COMMENT '启用状态:0->禁用;1->启用'
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COMMENT='权限表';

用户-角色关联表

该表主要记录某一用户具有哪些角色。

1
2
3
4
5
6
7
DROP TABLE IF EXISTS `admin_role`;
CREATE TABLE `admin_role`  (
  `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `admin_id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL,
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COMMENT='用户-角色关联表';

角色-权限关联表

该表主要记录某一角色具有哪些权限。

1
2
3
4
5
6
7
DROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission` (
  `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `role_id` int(11) NOT NULL,
  `permission_id` int(11) NOT NULL,
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COMMENT='角色-权限关联表';

总体来说RBAC在理解上并不算很难,我在学习的过程中时间主要花费在了数据库的设计和实现方面,在使用上也确实可以很方便的对系统进行权限管理,有很大的通用性