Mybatis实现RBAC权限模型查询

RBAC权限模型

Role-Based Access Control,中文意思是:基于角色(Role)的访问控制。这是一种广泛应用于计算机系统和网络安全领域的访问控制模型。

简单来说,就是通过将权限分配给➡角色,再将角色分配给➡用户,来实现对系统资源的访问控制。一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,用户与角色之间,角色与权限之间,一般者是多对多的关系
具体概念可以查看RBAC——基于角色权限的模型

这里我只演示如何在Mybatis中实现RBAC权限模型的查询

现在有四张表

CREATE TABLE `user`
(`username` varchar(50)  NOT NULL,`password` varchar(200) NOT NULL,`name`     varchar(50),PRIMARY KEY (`username`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;-- 创建角色表
CREATE TABLE `role`
(`id`   int(11) NOT NULL AUTO_INCREMENT,`name` varchar(50),PRIMARY KEY (`id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;-- 创建用户角色表
CREATE TABLE `user_role`
(`username` varchar(50),`role_id`  int(11),PRIMARY KEY (`username`, `role_id`),FOREIGN KEY (`role_id`) REFERENCES `role` (`id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;-- 创建菜单表
CREATE TABLE `menu`
(`id`        int(11) NOT NULL AUTO_INCREMENT,`name`      varchar(50),`parent_id` int(11),PRIMARY KEY (`id`),FOREIGN KEY (`parent_id`) REFERENCES `menu` (`id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;-- 创建角色菜单表
CREATE TABLE `role_menu`
(`role_id` int(11),`menu_id` int(11),PRIMARY KEY (`role_id`, `menu_id`),FOREIGN KEY (`role_id`) REFERENCES `role` (`id`),FOREIGN KEY (`menu_id`) REFERENCES `menu` (`id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;# ------------------------------------------------------------------------- 插入用户数据
INSERT INTO user (username, password, name) VALUES ('user1', 'password1', 'User 1');
INSERT INTO user (username, password, name) VALUES ('user2', 'password2', 'User 2');-- 插入角色数据
INSERT INTO role (name) VALUES ('file_role');
INSERT INTO role (name) VALUES ('db_role');-- 插入用户角色数据
INSERT INTO user_role (username, role_id) VALUES ('user1', 1);
INSERT INTO user_role (username, role_id) VALUES ('user2', 2);-- 插入菜单数据
INSERT INTO menu (name, parent_id) VALUES ('File', NULL);
INSERT INTO menu (name, parent_id) VALUES ('Database', NULL);
INSERT INTO menu (name, parent_id) VALUES ('File Access', 1);
INSERT INTO menu (name, parent_id) VALUES ('Database Access', 2);-- 插入角色菜单数据
INSERT INTO role_menu (role_id, menu_id) VALUES (1, 3);
INSERT INTO role_menu (role_id, menu_id) VALUES (2, 4);

image-20240705093050802
根据表分析,其实具有对应实体类的表只有user用户表和menu菜单表,其他的表都是用来关联和描述关系的,所以实体类只需要User和Menu

准备实体类User、Menu

@Data
public class User {private String username;private String password;private String name;private Menu menu;//一个用户只有一个菜单
}
//-------------------------------------------------
@Data
public class Menu {private Integer id;private String name;private Integer parentId;private List<Menu> sonMenus;//一个父级菜单下可能有多个子菜单
}

准备userMapper接口

public interface UserMapper {// 使用mybatis完成任意用户拥有的菜单查询List<User> getUsers();//使用mybatis的级联查询完成菜单的查询(包含子菜单)List<User> getUsersInclude();
}

准备userMapper.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.cnmd.mapper.UserMapper"><resultMap id="map1" type="user"><result property="username" column="username"/><result property="name" column="name"/><association property="menu" javaType="menu"><id property="id" column="menuId"/><result property="name" column="menuName"/><result property="parentId" column="menuParentId"/></association></resultMap><!--任意用户拥有的菜单查询--><select id="getUsers" resultMap="map1">SELECT u.username, u.name, m.name menuName, m.id menuId, m.parent_id menuParentIdFROM rbac.user uJOIN rbac.user_role ur ON u.username = ur.usernameJOIN rbac.role r ON ur.role_id = r.idJOIN rbac.role_menu rm ON r.id = rm.role_idJOIN rbac.menu m ON rm.menu_id = m.id;</select><!-- ================================================================ --><resultMap id="map2" type="user"><result property="username" column="username"/><result property="name" column="name"/><association property="menu" javaType="menu"><result property="name" column="parent_menu_name"/><collection property="sonMenus" ofType="menu"><result property="name" column="son_menu_name"/></collection></association></resultMap><!--完成菜单的查询(包含子菜单)--><select id="getUsersInclude" resultMap="map2">SELECT u.username, u.name, mp.name as parent_menu_name, m.name as son_menu_nameFROM rbac.user uJOIN rbac.user_role ur ON u.username = ur.usernameJOIN rbac.role r ON ur.role_id = r.idJOIN rbac.role_menu rm ON r.id = rm.role_idJOIN rbac.menu m ON rm.menu_id = m.idJOIN rbac.menu mp ON m.parent_id = mp.id;</select></mapper>

Java代码

SqlSession session = MybatisUtil.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);List<User> users = mapper.getUsers();
users.forEach(System.out::println);System.out.println("====================================");List<User> usersInclude = mapper.getUsersInclude();
usersInclude.forEach(System.out::println);

查询结果

User(username=user1, password=null, name=User 1, menu=Menu(id=3, name=File Access, parentId=1, sonMenus=null))
User(username=user2, password=null, name=User 2, menu=Menu(id=4, name=Database Access, parentId=2, sonMenus=null))====================================User(username=user1, password=null, name=User 1, menu=Menu(id=null, name=File, parentId=null, sonMenus=[Menu(id=null, name=File Access, parentId=null, sonMenus=null)]))
User(username=user2, password=null, name=User 2, menu=Menu(id=null, name=Database, parentId=null, sonMenus=[Menu(id=null, name=Database Access, parentId=null, sonMenus=null)]))

如果需要单独完成菜单的查询(包含子菜单)
只需要重新创建MenuMapper接口

public interface MenuMapper {List<Menu> getMenus();
}

创建MenuMapper.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="cn.cnmd.mapper.MenuMapper"><resultMap id="map" type="menu"><id property="id" column="parent_menu_id"/><result property="name" column="parent_menu_name"/><collection property="sonMenus" ofType="menu"><id property="id" column="son_menu_id"/><result property="name" column="son_menu_name"/></collection></resultMap><select id="getMenus" resultMap="map">SELECT m.id parent_menu_id, m.name as parent_menu_name, ms.id son_menu_id, ms.name as son_menu_nameFROM rbac.menu mJOIN rbac.menu msON m.id = ms.parent_id;</select></mapper>

查询结果

Menu(id=1, name=File, parentId=null, sonMenus=[Menu(id=3, name=File Access, parentId=null, sonMenus=null)])
Menu(id=2, name=Database, parentId=null, sonMenus=[Menu(id=4, name=Database Access, parentId=null, sonMenus=null)])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/373419.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

凝思安全操作系统安装部署

原文链接&#xff1a;凝思安全操作系统安装部署 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于凝思安全操作系统安装部署的文章。凝思安全操作系统是一款注重安全和隐私保护的操作系统&#xff0c;适用于各种高安全性需求的场景。本文将详细介绍如何安装和部署…

阿里云人工智能平台PAI部署开源大模型chatglm3之失败记录--update:最后成功了!

想学习怎么部署大模型&#xff0c;跟着网上的帖子部署了一个星期&#xff0c;然而没有成功。失败的经历也是经历&#xff0c;记在这里。 我一共创建了3个实例来部署chatglm3&#xff0c;每个实例都是基于V100创建的&#xff08;当时没有A10可选了&#xff09;&#xff0c;其显…

科普文:K8S中常见知识点梳理

简单说一下k8s集群内外网络如何互通的 要在 Kubernetes&#xff08;k8s&#xff09;集群内外建立网络互通&#xff0c;可以采取以下措施&#xff1a; 使用service&#xff1a; 使用Service类型为NodePort或LoadBalancer的Kubernetes服务。这可以使服务具有一个公共IP地址或端口…

CodeNavi 中代码表达式的节点和节点属性

本文分享自华为云社区《CodeNavi 中代码表达式的节点和节点属性》。作者&#xff1a;Uncle_Tom 1. 前期回顾 《寻找适合编写静态分析规则的语言》 根据代码检查中的一些痛点&#xff0c;提出了希望寻找一种适合编写静态分析规则的语言。 可以满足用户对代码检查不断增加的各种需…

SpringCloudAlibaba Nacos配置中心与服务发现

目录 1.配置 1.1配置的特点 只读 伴随应用的整个生命周期 多种加载方式 配置需要治理 1.2配置中心 2.Nacos简介 2.1特性 服务发现与服务健康检查 动态配置管理 动态DNS服务 服务和元数据管理 3.服务发现 1.配置 应用程序在启动和运行的时候往往需要读取一些配置信…

收银系统源代码-收银端UI风格

智慧新零售收银系统是一套线下线上一体化收银系统&#xff0c;给商户提供含线下收银称重、线上商城、精细化会员管理、ERP进销存、丰富营销活动、移动店务助手等一体化的解决方案。 如Windows版收银&#xff08;exe安装包&#xff09;、安卓版收银&#xff08;apk安装包&#…

HTML【详解】超链接 a 标签的四大功能(页面跳转、页内滚动【锚点】、页面刷新、文件下载)

超链接 a 标签主要有以下功能&#xff1a; 跳转到其他页面 <a href"https://www.baidu.com/" target"_blank" >百度</a>href&#xff1a;目标页面的 url 地址或同网站的其他页面地址&#xff0c;如 detail.htmltarget&#xff1a;打开目标页面…

关于【AI绘画】的学习

AI绘画中有个牛器DeepArt,也有很多AI软件和平台可以去借鉴和学习。 这里是一张AI绘画图片,主题是一个梦幻般的森林,里面充满了发光的蘑菇和飞舞的萤火虫: AI绘画资源 对于AI绘画,你可以参考一些在线平台和软件,它们提供了AI绘画的功能或者教程。此外,也可以寻找相关的书…

景芯SoC训练营DFT debug

景芯训练营VIP学员在实践课上遇到个DFT C1 violation&#xff0c;导致check_design_rule无法通过&#xff0c;具体报错如下&#xff1a; 遇到这个问题第一反映一定是确认时钟&#xff0c;于是小编让学员去排查add_clock是否指定了时钟&#xff0c;指定的时钟位置是否正确。 景芯…

神领物流项目第一天

文章目录 聚焦快递领域首先第一个是验证码模块流程登录接口权限管家 聚焦快递领域 首先第一个是验证码模块流程 首先生成验证码的流程 可以使用工具类去生成验证码 LineCaptcha lineCaptcha CaptchaUtil.createLineCaptcha(160, 60, 4, 26);// 获取值然后存入redis中 strin…

WPF引入多个控件库使用

目的 设计开发时有的控件库的一部分符合我们想要的UI样式&#xff0c;另一部分来自另一个控件库&#xff0c;想把两种库的样式做一个整合在同一个控件资源上。单纯通过引用的方式会导致原有样式被覆盖。这里通过设置全局样式的方式来实现。 1.安装控件库nuget包&#xff1a;H…

分享中国-吉林省和9个地级市州人文地图

分享中国-吉林省和9个地级市州人文地图 1、吉林省 吉林省&#xff0c;位于中国东北地区中部&#xff0c;地处东北亚地理中心位置&#xff0c;因吉林市而得名&#xff0c;清康熙时在松花江畔建吉林乌拉城&#xff0c;满语意为“沿江的地方”。 吉林省以中部大黑山为界&#x…

git为文件添加可执行权限

查看文件权限 git ls-files --stage .\SecretFinder.py100644 表示文件的所有者有读取和写入权限 添加可执行权限 git update-index --chmod x .\SecretFinder.py再次查看文件权限 git ls-files --stage .\SecretFinder.py100755 表示文件的所有者有读取、写入和执行权限

记录|C#安装+HslCommunication安装

记录线索 前言一、C#安装1.社区版下载2.VS2022界面设置 二、HslCommunication安装1.前提2.安装3.相关文件【重点】 更新记录 前言 初心是为了下次到新的电脑上安装VS2022做C#上机位项目时能快速安装成功。 一、C#安装 1.社区版下载 Step1. 直接点击VS2022&#xff0c;跳转下…

PostgreSQL 里怎样解决多租户数据隔离的性能问题?

文章目录 一、多租户数据隔离的性能问题分析&#xff08;一&#xff09;大规模数据存储和查询&#xff08;二&#xff09;并发访问和锁争用&#xff08;三&#xff09;索引维护成本高&#xff08;四&#xff09;资源分配不均 二、解决方案&#xff08;一&#xff09;数据分区&a…

【源码+方案】SRM供应商采购管理PPT(原件)

1、供应商管理流程 2、供应源搜寻 3、供应商评估 4、供应商选择 5、供应商考核评定 6、供应商关系管理 7、供应商开发 本文源码建设方案及软件全套资料获取&#xff1a;本文末个人名片直接获取或者进主页。

数据结构双向循环链表

主程序 #include "fun.h" int main(int argc, const char *argv[]) { double_p Hcreate_head(); insert_head(H,10); insert_head(H,20); insert_head(H,30); insert_head(H,40); insert_tail(H,50); show_link(H); del_tail(H); …

QT--SQLite

配置类相关的表&#xff0c;所以我使用sqlite,且QT自带该组件&#xff1b; 1.安装 sqlite-tools-win-x64-3460000、SQLiteExpert5.4.31.575 使用SQLiteExpert建好数据库.db文件&#xff0c;和对应的表后把db文件放在指定目录 ./db/program.db&#xff1b; 2.选择sql组件 3.新…

Qt 异步实现事件的定时执行 - QTimer和QThread的联合使用

异步实现事件的定时执行 - QTimer和QThread的联合使用 引言一、核心源码二、其信号和槽函数简述三、定时器及其moveToThread简述 引言 在 Qt 中&#xff0c;如果想要定时执行某些事件或函数&#xff0c;通常会使用 QTimer 类。QTimer 允许设置一个时间间隔&#xff0c;当这个时…

Linux镜像源设置不再难:一键脚本,新手也能成为优化高手(一键切换镜像源/Docker一键安装脚本)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 更换镜像源 📒📝 一键切换软件源📝 Docker一键安装脚本⚓️ 相关链接 ⚓️📖 介绍 📖 在国内,Linux系统用户经常会遇到下载软件包时速度慢的问题,这通常是因为默认的镜像源并不总是最优选择。对于新手来说,手动设置…