RBAC
RBAC基于角色的访问控制,RBAC认为权限授权的过程可以抽象地概括为:Who是否可以对What进行How的访问操作
RBAC简介
基于角色的权限访问控制模型
在RBAC模型里面,有3个基础组成部分,分别是:用户、角色和权限。RBAC通过定义角色的权限,并对用户授予某个角色从而来控制用户的权限,实现了用户和权限的逻辑分离(区别于ACL模型),极大地方便了权限的管理:
- User(用户):每个用户都有唯一的UID识别,并被授予不同的角色
- Role(角色):不同角色具有不同的权限
- Permission(权限):访问权限
- 用户-角色映射:用户和角色之间的映射关系
- 角色-权限映射:角色和权限之间的映射
RBAC支持三个著名的安全原则:最小权限原则、责任分离原则和数据抽象原则
- 最小权限原则:RBAC可以将角色配置成其完成任务所需的最小权限集合
- 责任分离原则:可以通过调用相互独立互斥的角色来共同完成敏感的任务,例如要求一个计账员和财务管理员共同参与统一过账操作
- 数据抽象原则:可以通过权限的抽象来体现,例如财务操作用借款、存款等抽象权限,而不是使用典型的读、写、执行权限
优点:
- 简化了用户和权限的关系
- 易扩展、易维护
缺点:
- RBAC模型没有提供操作顺序的控制机制,这一缺陷使得RBAC模型很难适应哪些对操作次序有严格要求的系统
RBAC的3种模型
- RBAC0,是最简单、最原始的实现方式,也是其他RBAC模型的基础
- RBAC1基于RBAC0模型,引入了角色间的继承关系,即角色上有了上下级的区别。
- RBAC2基于RBAC0模型的基础上,进行了角色的访问控制。
RBAC数据表设计
数据库 create database test default character set utf8mb4;
表和表之间的关系:1对1、1对多或者多对1、多对多
1对1实现方式
具体的实现方式有2种:共享主键和唯一外键。例如员工信息和登录账号
共享主键
扫描二维码关注公众号,回复:
15099783 查看本文章
create table if not exists tb_emps(
id bigint primary key auto_increment comment '雇员编号',
name varchar(32) not null comment '姓名',
sex boolean default 1 comment '性别',
education varchar(32),
birth date comment '出生日期',
hire_date date comment '入职日期',
salary numeric(8,2) comment '月薪'
)engine=innodb default charset utf8 comment '雇员信息';
create table if not exists tb_users(
id bigint primary key comment '用户编号',
foreign key(id) references tb_emps(id) on delete cascade,
username varchar(32) not null unique comment '用户名称',
password varchar(32) not null comment '用户口令',
create_time datetime default now() comment '创建时间',
update_time timestamp default current_timestamp on update
current_timestamp comment '修改时间',
salt varchar(32) comment 'md5加密的盐值',
user_locked boolean default 0 comment '账户是否锁定'
)engine=innodb default charset utf8 comment '登录账户';
唯一外键
create table if not exists tb_emp(
id bigint primary key auto_increment,
......
)engine=innodb default charset utf8;
create table if not exists tb_user(
id bigint primary key auto_increment,
... ...
emp_id bigint not null unique,
foreign key(emp_id) references tb_emp(id) on delete cascade
)engine=innodb default charset utf8;
1对多或者多对1
实现方式就是主外键关联,在关系型数据库使用最多的,例如雇员和部门
create table tb_dept(
id bigint primary key auto_increment,
name varchar(32) not null,
address varchar(50)
);
create table tb_emp(
id bigint primary key auto_increment,
name varchar(32) not null,
... ...,
dept_id bigint,
foreign key(dept_id) references tb_dept(id)
);
多对多
实际上关系型数据库中不直接支持多对多关系,必须引入中间表。例如学生选课
create table tb_student(
id bigint primary key auto_increment,
... ....
);
create table tb_course(
id bigint primary key auto_increment,
......
);
create table tb_choice(
student_id bigint not null,
course_id bigint not null,
primary key(student_id,course_id),
foreign key(student_id) references tb_student(id) on delete cascade,
foreign key(course_id) references tb_course(id) on delete cascade
);
权限控制表的实现
-
用户信息表用于存储登录用户相关数据,例如用户名、口令等。主要用于判断访问的用户是否为某个用户
create table tb_users( id bigint primary key auto_increment comment '代理主键', username varchar(32) not null, password varchar(32) not null, ... ... );
-
角色表,角色可以理解为一组权限的别名,不等于职位。
create table tb_roles(
id bigint primary key auto_increment,
title varchar(32) not null unique,
... ...
);
- 权限表,系统中为了简化开发,经常和菜单表合并,从而实现方便定义的目的。在具体的应用中通过菜单向是否显示以达到权限控制的目的。具体应用中针对菜单需要考虑使用无限级分类
create table tb_privs(
id bigint primary key auto_increment,
title varchar(32) not null comment '菜单项标题',
url varchar(50) comment '点击菜单后跳转的目标地址',
parent_id bigint comment '用于表示当前菜单项是哪个菜单项的子菜单',
foreign key(parent_id) references tb_privs(id) on delete cascade,
chilren boolean default 0 comment '不是必须的列,是为了编程方便引入的额外列,用于表示是否有子菜单项'
-- 还可有其它和编程相关的列,例如层级等
);
样例数据
id | title | url | parent_id | children |
---|---|---|---|---|
1 | 商品管理 | null | null这里使用parent_id为null表示根菜单项 | 1 |
2 | 新增商品 | /products/add | 1 | 0 |
3 | 删除商品 | /products/del | 1 | 0 |
- 用于表示用户和角色之间关系的表,因为用户和角色之间是多对多关联,所以必须引入中间表
create table tb_users_roles(
user_id bigint not null,
role_id bigint not null,
primary key(user_id,role_id),
foreign key(user_id) references tb_users(id) on delete cascade,
foreign key(role_id) references tb_roles(id) on delete cascade
);
- 用于表示角色和权限之间关系的表,因为角色和权限之间是多对多关联,所以必须引入中间表
create table tb_roles_privs(
role_id bigint not null,
priv_id bigint not null,
primary key(role_id,priv_id),
foreign key(role_id) references tb_roles(id),
foreign key(priv_id) references tb_privs(id)
);
- 根据业务需求,还有可能会出现需要将一些权限直接授予给某个用户的问题,如果需要支持这个功能,还需要创建用户和权限之间的中间表