开端

其实这不是个开端,是我在写 Shiro 整合 SSM 的时候写不下去了,想重新开一篇来写。。。高考语文 80 分,实在憋不出来写啥了啊哈哈哈。

emmm 回归正题,这次我们来讲一讲 RBAC 模型的权限处理,以及基于这个模型我们该如何设计数据表。我在刚做项目的时候其实完全没有考虑到这块内容,我觉得权限只要一个用户一个角色,前端根据用户登录时获取到的角色信息进行接口的放行或者禁止就可以了。仔细想一想确实有很多漏洞,比如我直接使用 Postman 对一些需要权限才能调用的接口进行访问等等;再比如我的 token 是前端直接生成的,而没有利用 session、cookie 等技术,如果有人直接往自己浏览器的 sessionStorage 里存一个管理员 token 不就可以获得最高权限了吗,这显然是不可取的。

权限,应当是一个系统最先进行考虑的,之后才是在权限的基础上 CURD CURD CURD 。。。我们先来看看对权限模型的思考吧。

解析

接下来进入正题。

权限模型

首先来分析一下我们目前比较常用的一些权限模型。

传统权限模型

一般来说的传统权限模型并没有什么复杂的内容,就是我开头讲到的最基本的用户和权限之间的绑定。我数据库里存了三个用户,那么给每个用户都分配各自的权限。但是业务复杂起来,用户多起来之后就会发现问题了。这样的方式绑定权限,删改不够灵活。用户不可能每个人的权限都各不相同,总有一些相同类别的用户,他们需要相同的权限。比如说管理员老王和其他管理员都要拥有系统所有的权限,这样才能方便测试接口,如果管理员都没有权限,这个操作还有什么意义。

再比如吃瓜群众这类人,他也就只能登陆系统查查基本的数据,对于修改尤其是添加和删除是完全没有任何权限的,修改也仅限于自己的头像啊密码啊什么的。那当一类人到达一定基数的时候,我们是不是可以将他们的角色给抽离出来,独自形成一层。这就是我接下来讲到的 RBAC (Role-Base Access Control)。

RBAC0 权限模型

按照英文来解释,就是基于角色的权限控制。所以显而易见,他在传统的权限模型里又加了角色。我们在传统模型中是直接将权限赋予用户。而在这个模型中,现将权限赋予角色,再把角色赋予用户,这样的分层是不是就更加清晰了。就和学校里一样,校领导管一批院领导,院领导管各自的年级专业,每一个年级专业再分班分学号给每一位同学。和我既是属于计算机专业的,又是属于机电系的是一个道理。

但是我这个图其实还有点问题,大家可以发现我画的每一个用户只对应了一个角色,在实际操作中往往是用户和角色之间是一对多的关系,而且同一角色内部也有细分。试想一下,如果老王和老贾都是管理员,但是老王等级更高一些。老贾只是个新来的,但是他们所拥有的权限是一样的。老王是不是就有意见,万一哪天老贾一个删库到跑路把锅甩给老王那可咋办?所以接下来又在这个基础上派生出几个不同的权限模型。

RBAC1角色分层模型

为了解决老王内心的不愉快,我就只能给管理员分成两个等级,其他角色也同样操作。这样一来,我可以通过同一角色之间不同等级的权限分级,给他们分配不同的权限。换一种角度来说这其实和多分配了几个角色没有区别,但是给角色分级之后同一角色不同等级之间耦合度更高一些,可能只有少数权限不相同。

随着角色的增多,分级的增加,问题又来了。吃瓜群众中奖被选为我们软件的内测人员,终于可以从普通低级用户变为低级检错员了,但是他作为普通用户的一些权限仍旧保留,那该怎么办?所以接下来又有一种权限模型的想法诞生了。

RBAC2 角色限制模型

这种模型比较难用图来表示,简单的来说就是可以限制一个用户拥有多个角色的时候只能同时激活一个角色,或者用高级的角色包含住低级的角色,然后规定用户必须从低级角色升级到高级角色,仅保留高级角色的权限。完全应用这种模型的场合并不太多。

RBAC3 统一模型

RBAC3 = RBAC2 + RBAC1

这种模型是前两种的结合体,相对来说更加复杂,很少会考虑这么做,就不多赘述。

模型的选择

其实对于一个系统来说,权限是根据需求来定的,并不是一定要按照上述的几种来写,每一种权限模型都有它的特点,有优势有缺陷。所以我们在开发的时候,要根据自己的项目来确定权限模型。就好比我自己做的小项目比较简单,没有涉及很多用户。所以就只设置了管理员、学生、教师三种不同的角色,然后每一个用户只能同时激活一个角色,最后再给每个角色分配权限。

MySQL建表

对于 Shiro 下的权限数据表,一般来说比较正规的都是采用权限五表。首先用户数据肯定需要一张表来存,其次是权限数据的一张表。当我们采用 RBAC 模型时,角色也需要一张表来存。那么如何将这三张表之间相互关联呢,我们就需要另外的一张用户-角色表,以及一张角色-权限表,可以将主要的三张表之间的主键一一关联起来。我们就来看一下这五张表的建表语句吧:

-- create database shiro default character set utf8;

drop table if exists sys_users;
drop table if exists sys_roles;
drop table if exists sys_permissions;
drop table if exists sys_users_roles;
drop table if exists sys_roles_permissions;

create table sys_users (
  id bigint auto_increment comment '编号',
  username varchar(100) comment '用户名',
  password varchar(100) comment '密码',
  salt varchar(100) comment '盐值',
  role_id varchar(50) comment '角色列表',
  locked bool default false comment '是否锁定',
  constraint pk_sys_users primary key(id)
) charset=utf8 ENGINE=InnoDB;
create unique index idx_sys_users_username on sys_users(username);

create table sys_roles (
  id bigint auto_increment comment '角色编号',
  role varchar(100) comment '角色名称',
  description varchar(100) comment '角色描述',
  pid bigint comment '父节点',
  available bool default false comment '是否锁定',
  constraint pk_sys_roles primary key(id)
) charset=utf8 ENGINE=InnoDB;
create unique index idx_sys_roles_role on sys_roles(role);

create table sys_permissions (
  id bigint auto_increment comment '编号',
  permission varchar(100) comment '权限编号',
  description varchar(100) comment '权限描述',
  rid bigint comment '此权限关联角色的id',
  available bool default false comment '是否锁定',
  constraint pk_sys_permissions primary key(id)
) charset=utf8 ENGINE=InnoDB;
create unique index idx_sys_permissions_permission on sys_permissions(permission);

create table sys_users_roles (
  id  bigint auto_increment comment '编号',
  user_id bigint comment '用户编号',
  role_id bigint comment '角色编号',
  constraint pk_sys_users_roles primary key(id)
) charset=utf8 ENGINE=InnoDB;

create table sys_roles_permissions (
  id bigint auto_increment comment '编号',
  role_id bigint comment '角色编号',
  permission_id bigint comment '权限编号',
  constraint pk_sys_roles_permissions primary key(id)
) charset=utf8 ENGINE=InnoDB;

总结

那么今天主要是讲了几个比较常用的权限模型,以及在 RBAC 权限模型下 MySQL 如何进行建表。至于在 RBAC 的基础上如何整合 Shiro 和 SSM、VUE 项目,我会在下一篇中进行讲解。

最后修改:2022 年 05 月 27 日
随意