当前位置: 首页 > news >正文

若依(RuoYi )权限管理设计

前言

若依权限管理包含两个部分:菜单权限数据权限。菜单权限控制着我们可以执行哪些操作。数据权限控制着我们可以看到哪些数据。

菜单是一个概括性名称,可以细分为目录菜单按钮,以若依自身为例:

  • 目录,就是页面导航,也可以理解为导航父菜单(二级导航或三级导航)如:系统管理;某个父菜单没有权限,表示需要隐藏或禁用这个父菜单。
  • 菜单,就是导航子菜单,如:用户管理;某个子菜单没有权限,表示需要隐藏或禁用这个子菜单,也就无法进入子菜单关联的页面,如:用户管理页面。
  • 按钮,可以泛化理解为页面组件,如:新增;某个组件没有权限,表示需要隐藏或禁用这个组件,也就无法执行这个组件关联的事件,如:点击。

菜单权限

菜单权限是基于 角色 实现的,如下图:

菜单授权

  1. 创建或编辑菜单时,设置菜单权限字符,相当于菜单唯一标识符;
  2. 创建或编辑角色时,设置该角色拥有权限的菜单列表,即:角色关联菜单权限标识符;
  3. 创建或编辑用户时,设置该用户拥有的角色列表,即:角色关联用户;

菜单鉴权

验证用户对于菜单是否有权限,可以通过角色实现:

  1. 获取用户拥有的角色列表;
  2. 如果角色列表包含这个角色,则表示有权限;否则,表示没有权限。

也可以通过菜单权限字符实现:

  1. 获取用户拥有的角色列表;
  2. 获取这些角色拥有权限的菜单(权限字符)列表;
  3. 如果菜单列表包含这个菜单,则表示有权限;否则,表示没有权限。

前端鉴权

前端使用菜单鉴权时,需要使用权限指令:

// 角色
<el-button v-hasRole="['admin']">管理员才能看到</el-button>

// 权限字符
<el-button v-hasPermi="['system:user:add']">存在权限字符串才能看到</el-button>

后端鉴权

前端鉴权只能保证可以隐藏或禁用菜单,并不能保证菜单关联的后端接口请求不被非法调用,若依支持在后端接口方法使用角色或权限字符声明权限:

// 角色
@PreAuthorize("@ss.hasRole('user')")

// 权限字符
@PreAuthorize("@ss.hasPermi('system:user:list')")

若依没有为后端接口专门设计权限管理模块,它认为后端接口和菜单具有对应关系,可以直接使用菜单的角色或权限字符用于后端接口的权限声明。

数据权限

数据权限也是基于 角色 实现的,如下图:

支持五种权限模式,按权限大小依次排列:

  • 全部数据权限,表示拥有所有部门的数据权限
  • 自定数据权限,表示拥有指定的若干部门的数据权限
  • 本部门数据权限,表示仅拥有用户所属部门(不包括子部门)的数据权限
  • 本部门及以下数据权限,表示仅拥有用户所属部门和所有子部门的数据权限
  • 仅本人数据权限,表示仅拥有用户本人的数据权限

数据模式需要使用 用户部门。这就要求我们创建数据表时,除业务数据自身字段以外,需要额外增加两个字段:

  • userId,表示用户 ID;
  • deptId,表示部门 ID;

用户可以拥有多个角色,但只能属于一个部门。
部门支持有父子关系,角色不支持父子关系。

数据授权

  1. 创建或编辑部门时,设置部门父子关系;
  2. 创建或编辑角色时,设置角色的数据权限模式;如果是自定数据权限,需要设置部门列表;

数据鉴权

数据鉴权实际是数据过滤,即:过滤用户没有权限的数据。实际使用时,我们只需要在查询数据的方法上添加注解:

@DataScope

声明启用数据过滤即可。这样若依查询数据时,仅会返回用户有权限的数据。

若依对于使用数据权限的数据方法实现是有一定要求的,我们不描述具体细节,仅给出核心流程:

  1. 获取用户的角色列表;
  2. 获取这些角色的数据权限模式;
  3. 计算这些数据权限中的最大权限;
  4. 根据这个最大权限,转换成该权限对应的部门 ID(一个或多个) 或 用户 ID;
  5. 动态修改查询数据方法的查询 SQL 语句,添加基于部门 ID 或用户 ID 的过滤语句;
  6. 执行修改后的查询 SQL 语句;

可以看出,数据权限本质上就是基于部门 ID 或用户 ID 的数据过滤,只是这个过滤是若依为我们自动完成的。

结语

若依的菜单权限和数据权限都是基于 角色 实现的,用户关联着角色,角色关联着菜单权限字符和数据权限模式。

相关文章:

  • 【024】 快速上手mongoose web服务器
  • DevOps自动化测试的原则和实践
  • `SpringBoot`+`axios`结合发送`ajax`请求
  • 电子元器件产业发展遇新机,SRM供应商协同管理系统实现与供应商的敏捷协同
  • C#基础入门教程-基本语法
  • TensorRT安装记录(8.2.5)
  • C++ 池式组件 线程池 内存池 异步请求池 MySQL连接池
  • SwiftUI 动态岛开发教程之 05 Dynamic Island 和 Live Activity 无需太多代码即可为用户提供大量信息
  • XDU2019级保研数据统计分析
  • 网课查题使用方法
  • 在 Ubuntu 新装系统中安装 ruby 的几点注意
  • 按行分块和按列分块
  • 【Vue3】穿梭框 -- 思路与实现分析
  • SpringBoot读取yml配置文件
  • 制胜充电桩下半场,特来电、星星充电们要靠运营?
  • 【译】JS基础算法脚本:字符串结尾
  • $translatePartialLoader加载失败及解决方式
  • E-HPC支持多队列管理和自动伸缩
  • ES6--对象的扩展
  • es的写入过程
  • Hibernate【inverse和cascade属性】知识要点
  • java2019面试题北京
  • js作用域和this的理解
  • MySQL数据库运维之数据恢复
  • Netty 4.1 源代码学习:线程模型
  • Python3爬取英雄联盟英雄皮肤大图
  • text-decoration与color属性
  • use Google search engine
  • 编写高质量JavaScript代码之并发
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 解决iview多表头动态更改列元素发生的错误
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 马上搞懂 GeoJSON
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 微信开源mars源码分析1—上层samples分析
  • 学习Vue.js的五个小例子
  • 浅谈sql中的in与not in,exists与not exists的区别
  • ​linux启动进程的方式
  • #NOIP 2014# day.2 T2 寻找道路
  • (C++17) std算法之执行策略 execution
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (十)T检验-第一部分
  • (图)IntelliTrace Tools 跟踪云端程序
  • (转载)Linux网络编程入门
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • ./configure,make,make install的作用
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET Core 项目指定SDK版本
  • .net core 依赖注入的基本用发
  • .NETCORE 开发登录接口MFA谷歌多因子身份验证
  • .NET开发不可不知、不可不用的辅助类(一)
  • /ThinkPHP/Library/Think/Storage/Driver/File.class.php  LINE: 48
  • @property括号内属性讲解
  • [20170713] 无法访问SQL Server