系统权限模块的几种实现策略

  1. 经典的RACB模式

racb模式是指在计算机系统中实现的一种安全访问控制模式,它包括四个组成部分,即角色、权限、用户和资源。

  1. 角色(role):角色是一组被授权执行某些特定任务或访问某些特定资源的权限集合。例如,管理员、普通用户等都可以视为不同的角色。

  1. 权限(authorization):权限是指允许角色对某些特定资源进行操作的能力。例如,读取、写入、删除等操作都可以作为不同的权限。

  1. 用户(user):用户是指系统中的个体,可以被分配到不同的角色中,从而获得相应的权限来访问资源。

  1. 资源(resource):资源是指计算机系统中需要被保护的对象,例如文件、数据库、网络服务等。

在racb模式中,角色与权限是紧密相关的,一个角色可以被赋予多个权限,一个权限也可以被分配给多个角色。用户通过被分配到不同的角色中,来获得不同的权限,从而访问相应的资源。

ER图

对应表结构

-- The following code generates the three tables required for the classic RBAC permission model:

CREATE TABLE `roles` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 前端路由菜单
CREATE TABLE menu (
  id INT PRIMARY KEY,
  icon VARCHAR(50),
  url VARCHAR(255) NOT NULL,
  keepAlive BOOLEAN,
  name VARCHAR(50),
  parentId INT,
  path VARCHAR(255),
  visible BOOLEAN
); 
-- Create table for relationship between menu and role 
CREATE TABLE role_menu(
  id INT NOT NULL AUTO_INCREMENT, 
  menu_id INT,
  role_id INT,
  PRIMARY KEY (`id`)
  FOREIGN KEY (menu_id) REFERENCES menu(id),
  FOREIGN KEY (role_id) REFERENCES role(id)
);
CREATE TABLE `permissions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `code` VARCHAR(100) comment '标识码,如sys:user:list',
  `url` VARCHAR(100) comment '后端接口关联url', 
  `description` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `role_permissions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role_id` int(11) NOT NULL,
  `permission_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `role_id` (`role_id`),
  KEY `permission_id` (`permission_id`),
  CONSTRAINT `role_permissions_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `role_permissions_ibfk_2` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

前后端权限控制流程

用户登录后,会获取自己拥有的权限信息,后端存储redis或cache缓存中,前端存储vuex、localSession、sessionStorage或cookie中,每次进行页面的加载,前端根据拥有的权限信息对系统页面或控件进行显示、禁用或隐藏,如vue加载动态路由后使用自定义权限认证指令v-permission进行显示、禁用或隐藏,后端对访问接口的用户做鉴权,如spring基于url鉴权的在controller层为需要权限资源访问控制的接口加上@PreAuthorize()权限表达式注解,可自定义权限校验逻辑(自定义实现切面实现或在springsecurity框架中过滤器配置中配置.antMatch()等)

  1. RBAC精简版

用法同上述RBAC大致一样,不同点在于将角色所有的permission以自定义分隔符的字符串形式冗余存储到roles表的permissions属性下 ,需要后端简单的分割获取。

优点:不用对数据库数据表连接处理获取权限数据,加快数据库响应速率。

对应表结构

CREATE TABLE `roles` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `permisssions` varchar(255),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 前端菜单路由
CREATE TABLE menu (
  id INT PRIMARY KEY,
  icon VARCHAR(50),
  keepAlive BOOLEAN default true,
  name VARCHAR(50) not null,
  menu_order INT,
  parentId INT,
  menu_route VARCHAR(255) NOT NULL,
  visible BOOLEAN default true
); 
-- Create table for relationship between menu and role 
CREATE TABLE role_menu(
  id INT NOT NULL AUTO_INCREMENT, 
  menu_id INT,
  role_id INT,
  PRIMARY KEY (`id`)
  FOREIGN KEY (menu_id) REFERENCES menu(id),
  FOREIGN KEY (role_id) REFERENCES role(id)
);

  1. RBAC扩展版

传统的RBAC可以满足后端对接口的权限控制,但对于有些前后端分离的架构中还存在着欠缺。

例如,我们使用v-show/v-permission等对前端控件用户管理的"编辑"按钮进行访问控制,对应的permission为/admin/user/edit

但弹窗的加载弹出还需要其他接口权限资源/admin/dept/list 部门列表和/admin/role/list角色列表

因此我们可以引入权限字表对RBAC进行扩展

ER图

权限资源

我们清楚,权限资源即后台访问的接口资源,一般所有需要授权访问的接口我们都需要为其配置对应的权限资源,以便在用户访问该接口时进行鉴权。即permissions资源权限表,后台接口依旧是对权限资源访问控制

权限资源管理的增删改操作的是permissions表

菜单

菜单比较好理解,即左侧菜单目录,和目录下的页面(表单)、按钮(编辑、新增等)

菜单管理增删改操作的是menus表, 可以在菜单管理中为菜单(按钮)分配一个或多个权限字,菜单关联多个权限字的页面配置。这个逻辑会比较复杂而且专业,通常是由系统实施工程师负责替企业用户配置的。

按钮级菜单只是一种通俗形象的称谓,而并非一定要和某个按钮进行一对一的强关联,这种关联属于权限字的职责范围。比如用户的需求是,要求为每个表单只设置“查看”和“编辑”两个菜单权限,这样业务系统管理员在给角色分配权限候,就会非常直观,同时由于按钮级菜单数量的减少,他们的工作量也会随之降低。还有一种业务场景,同一个页面中包含多个Tab容器,比如,基础信息、财务数据和生产数据等。每个Tab容器对应一个权限字标识。这个时候的按钮级菜单可能就是,“查看其他”、“查看财务”、“编辑其他”和“编辑财务”了。

权限字

一个权限字对应唯一的前端控件权限,如按钮、卡片,容器等。与权限资源是多对多关系,关联表为permission_code_permisssion

权限字管理增删改操作的是permissions_code表,可以在权限字管理中管理权限字对应的权限资源

为什么权限字和权限资源必须是多对多的关系呢?

因为一个权限字对应的组件,可能会触发多个后台接口的请求,比如卡片容器内组件的数据显示,可能需要加载一到多个后台接口返回的数据,才能渲染卡片容器内的所有子组件。反之亦然,同一个后台接口,也可能会被多个前端组件的操作所触发。由此可见,他们之间必然是多对多的关联关系。这种多对多的关系可以更灵活地管理权限,使得系统可以根据具体需求为每个用户或角色分配最合适的权限

例如,在一个电子商务系统中,管理员可能需要授予多个不同的权限给销售人员,以便他们能够管理订单、客户信息和产品目录等资源。而销售人员也可能需要访问多个不同的资源才能完成其工作,如查看订单、编辑客户信息和添加新产品等。因此,将权限字和资源之间建立多对多关系可以更好地满足不同用户和角色的需求。

例如橙单教学系统中权限字管理,点击编辑查看课程管理权限字片段的关联资源

可以看出课程管理页面权限字关联着两个受保护接口/admin/app/course/list/admin/app/course/download (courseId=?, fileName=?……)

因此,该课程管理表单的表格数据(对应唯一权限字)的加载,需要两个权限资源对应的后台接口才能被正常渲染

同理,编辑课程(权限字)也应该对应着两个权限资源分别为,/admin/app/course/view/admin/app/course/download

对应表结构

-- Create the menu table
CREATE TABLE menu (
  id INT PRIMARY KEY,
  icon VARCHAR(50),
  keepAlive BOOLEAN default true,
  name VARCHAR(50) not null,
  menu_order INT,
  parentId INT,
  menu_route VARCHAR(255) NOT NULL,
  visible BOOLEAN default true
); 
-- Create table for relationship between menu and role 
CREATE TABLE role_menu(
  id INT NOT NULL AUTO_INCREMENT, 
  menu_id INT,
  role_id INT,
  PRIMARY KEY (`id`)
  FOREIGN KEY (menu_id) REFERENCES menu(id),
  FOREIGN KEY (role_id) REFERENCES role(id)
);
CREATE TABLE menu_permission (
  id INT PRIMARY KEY,
  menu_id INT,
  permission_id INT,
  FOREIGN KEY (menu_id) REFERENCES menu(id),
  FOREIGN KEY (permission_id) REFERENCES permission_word(id)
);
CREATE TABLE permission_word (
  id INT PRIMARY KEY,
  permission_type tinyint COMMENT '【0表单,1片段,2操作】',
  display_order INT,
  permission_identifier VARCHAR(50) COMMENT '标识码如formStudent:formStudent:delete'
);
-- Create the permission_word_resource table to establish a many-to-many relationship between permission_word and permission_resource
CREATE TABLE permission_word_resource (
  id INT PRIMARY KEY,
  permission_word_id INT,
  permission_resource_id INT,
  FOREIGN KEY (permission_word_id) REFERENCES permission_word(id),
  FOREIGN KEY (permission_resource_id) REFERENCES permission_resource(id)
);

-- Create the permission resource table
CREATE TABLE permission_resource (
  id INT PRIMARY KEY,
  perm_name VARCHAR(50),
  url VARCHAR(100) comment '后端接口关联url', 
  code VARCHAR(100) comment '标识码,如sys:user:list',
  perm_module_id INT comment '一般保存在数据字典中'
);

上面叙述的三种实现权限管理的方案,各具优缺点,没有必要去对比,基于不同系统所需要的和你所能理解掌握的去选择即可。

在此之后的实现,有以下几种接口的控制策略

  • 基于角色的rbac

基于角色的rbac是最常见的实现方案。在这种模式下,用户被分配到特定的角色。每个角色都有一个或多个权限,而用户可以访问这些权限。这种模式的优点是易于理解和实现,并且易于维护。缺点是如果角色的数量很大,那么管理它们可能会变得很困难。

  • 基于属性的rbac (即本文所讲述的基于url的鉴权)

基于属性的rbac是另一种实现方案。在这种模式下,用户以及资源都具有某些属性。这些属性可以根据需要进行组合,从而确定用户是否有权访问特定资源。该模式的优点是更加灵活,可以适应更广泛的场景。缺点是实现和管理上可能会更加复杂。

  • 基于任务的rbac

基于任务的rbac是一种相对较新的实现方案。在这种模式下,用户被分配到特定的任务或工作流中。与角色不同,任务通常是短期的,并且可以在完成后重新分配。这种模式的优点是更加灵活,并且可以适应流程化的场景。缺点是对于长期运行的任务,管理可能会更加困难。

综上所述,rbac的最佳实现方案取决于具体情况。基于角色的rbac是最常见的实现方式,易于理解和实现,并且易于维护。如果需要更灵活的访问控制,则可以考虑使用基于属性的rbac或基于任务的rbac。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菠萝追雪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值