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

springboot实现ACL+RBAC权限体系

本文基于web系统的权限控制非常重要的前提下,从ALC和RBAC权限控制两个方面,介绍如何在springboot项目中实现一个完整的权限体系。

源码下载 :https://gitee.com/skyblue0678/springboot-demo

序章

一个后台管理系统,基本都有一套自己的权限体系,权限体系分两种分别是基于控制列表的权限,和基于角色的权限。

基于控制列表的权限,也叫ACL认证体系。就是每个权限,你可以理解为每一个controller方法都有一个自己的用户列表,只有存在于该列表的用户可以访问这个方法。

而基于角色的权限,就是每个用户有自己的角色,而角色拥有多个controller方法的访问权限,用户和角色,角色和接口都是多对多的关系。

ACL: Access Control List

简介:以前非常盛行的一种权限设计,它的核心主要在于用户和权限直接挂钩。

优点:简单易用、开发便捷。

缺点:用户是直接和权限挂钩,导致了在授予权限的时候的复杂性,比较分散,不太易于管理。

例子:常见的文件系统,直接给用户家权限。比如给用户加读写的权限。

RBAC:Role Based Access Control

简介:基于角色的访问控制系统。权限是与角色进行相关联,用户通过成为适当的角色成员从而得到这些角色的权限。

优点:简化了用户和权限的管理,用过对用户进行分类,使得其与角色和权限关联起来。

缺点:开发起来相对于ACL复杂。

例子:基于REAC模型的权限验证框架与应用Apache Shiro、Spring security。

第一章 ACL的权限控制

表结构设计

上面说了,ACL是权限和用户直接挂钩,我们需要设计数据库表来存储用户和权限信息。以下是简化的表结构设计:

sql:

DROP TABLE IF EXISTS `acl`;
CREATE TABLE `acl` (`id` int NOT NULL,`user_id` int DEFAULT NULL,`permission_id` int DEFAULT NULL,PRIMARY KEY (`id`),KEY `user_id` (`user_id`),KEY `permission_id` (`permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission` (`id` int NOT NULL AUTO_INCREMENT,`permission` varchar(50) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`id` int NOT NULL AUTO_INCREMENT,`username` varchar(50) DEFAULT NULL,`password` varchar(50) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

初始化数据:

-- 插入用户数据  
INSERT INTO User (id, username, password) VALUES (1, 'jack', '1');  
INSERT INTO User (id, username, password) VALUES (2, 'rose', '1');  -- 插入权限数据  
INSERT INTO Permission (id, permission) VALUES (1, 'device:list');  
INSERT INTO Permission (id, permission) VALUES (2, 'device:add');  -- 插入ACL数据  
INSERT INTO ACL (id, user_id, permission_id) VALUES (1, 1, 1);  
INSERT INTO ACL (id, user_id, permission_id) VALUES (2, 2, 2);

ACL权限设计代码

有了用户,权限,acl三张表后,就根据matisplus将对应的增删改查功能实现。

Mapper

public interface UserMapper extends BaseMapper<User> {
}public interface PermissionMapper extends BaseMapper<Permission> {
}public interface AclMapper extends BaseMapper<Acl> {
}

Service

public interface UserService  extends IService<User> {User getByUsername(String username);
}public interface PermissionService extends IService<Permission> {List<Permission> findByIds(Set<Integer> permIds);
}public interface AclService extends IService<Acl> {List<Permission> findByUserId(Integer id);
}

impl

@Service
@Slf4j
public class UserServiceImpl  extends ServiceImpl<UserMapper, User> implements UserService {@Overridepublic User getByUsername(String username) {return baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUserName,username));}
}@Service
@Slf4j
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {@Overridepublic List<Permission> findByIds(Set<Integer> permIds) {return baseMapper.selectBatchIds(permIds);}
}@Service
@Slf4j
public class AclServiceImpl extends ServiceImpl<AclMapper, Acl> implements AclService {@ResourcePermissionService permissionService;@Overridepublic List<Permission> findByUserId(Integer id) {List<Acl> acls = baseMapper.selectList(new LambdaQueryWrapper<Acl>().eq(Acl::getUserId, id));Set<Integer> permIds = acls.stream().map(Acl::getPermissionId).collect(Collectors.toSet());return permissionService.findByIds(permIds);}
}

最后是在login里面获取用户的权限

@GetMapping("/acl/login")
public String loginAcl(String username,String password){User user = userService.getByUsername(username);if(Objects.nonNull(user)){if(!user.getPwd().equals(password)){return "密码错误!";}//根据用户获取ACL权限列表List<Permission> permissionList = aclService.findByUserId(user.getId());return permissionList.toString();}else {return "用户名不存在";}
}

测试:

浏览器访问: http://localhost:8080/acl/login?username=jack&password=1

[Permission(id=1, permission=device:list)]

这个例子中,我们通过用户登录,获取了对应的权限列表,后续的章节中,我们会做真实的权限校验。

第二章 RBAC的权限控制

RBAC比ACL就是多了一个角色的概念,用户是拥有角色的,角色对应具体的权限,所以控制起来更加的灵活。

表结构设计

以下是简化的表结构设计:

sql

DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (`id` int NOT NULL AUTO_INCREMENT,`role_name` varchar(20) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;INSERT INTO `role` VALUES ('1', '设备管理员');DROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission` (`id` int NOT NULL AUTO_INCREMENT,`role_id` int DEFAULT NULL,`permission_id` int DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;INSERT INTO `role_permission` VALUES ('1', '1', '1');DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (`id` int NOT NULL AUTO_INCREMENT,`user_id` int DEFAULT NULL,`role_id` int DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;INSERT INTO `user_role` VALUES ('1', '1', '1');

RBAC的登录方法

@GetMapping("/rbac/login")
public String loginRbac(String username,String password){User user = userService.getByUsername(username);if(Objects.nonNull(user)){if(!user.getPwd().equals(password)){return "密码错误!";}//根据用户获取ACL权限列表List<Permission> permissionList = userService.findByUserRole(user.getId());return permissionList.toString();}else {return "用户名不存在";}
}

根据用户角色查询权限

@Override
public List<Permission> findByUserRole(Integer id) {return baseMapper.findByUserRole(id);
}

mapper

public interface UserMapper extends BaseMapper<User> {List<Permission> findByUserRole(@Param("id") Integer id);
}

xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.it.demo.mapper.UserMapper"><select id="findByUserRole" resultType="com.it.demo.entity.Permission">SELECTe.*FROMUSER aLEFT JOIN user_role b ON a.id = b.user_idLEFT JOIN role c ON b.role_id = c.idLEFT JOIN role_permission d ON c.id = d.role_idLEFT JOIN permission e ON d.permission_id = e.idWHEREa.id = #{id}</select>
</mapper>

访问:http://localhost:8080/rbac/login?username=jack&password=1

[Permission(id=1, permission=device:list)]

相关文章:

springboot实现ACL+RBAC权限体系

本文基于web系统的权限控制非常重要的前提下&#xff0c;从ALC和RBAC权限控制两个方面&#xff0c;介绍如何在springboot项目中实现一个完整的权限体系。 源码下载 &#xff1a;https://gitee.com/skyblue0678/springboot-demo 序章 一个后台管理系统&#xff0c;基本都有一套…...

C++20协程示例

C20协程示例 认识协程 在C中&#xff0c;协程就是一个可以暂停和恢复的函数。 包含co_wait、co_yield、co_return关键字的都可以叫协程。 看一个例子&#xff1a; MyCoroGenerator<int> testFunc(int n) {std::cout << "Begin testFunc" << s…...

【Verilog 教程】6.2Verilog任务

关键词&#xff1a;任务 任务与函数的区别 和函数一样&#xff0c;任务&#xff08;task&#xff09;可以用来描述共同的代码段&#xff0c;并在模块内任意位置被调用&#xff0c;让代码更加的直观易读。函数一般用于组合逻辑的各种转换和计算&#xff0c;而任务更像一个过程&a…...

Spring修炼之路(1)基础入门

一、简介 1.1Spring概述 Spring框架是一个轻量级的Java开发框架&#xff0c;它提供了一系列底层容器和基础设施&#xff0c;并可以和大量常用的开源框架无缝集成&#xff0c;可以说是开发Java EE应用程序的必备。Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器&…...

GANs学习记录

GAN 基于GAN的研究识别相关不同背景目标图像 可以用Augmentation2021.3.15 基于GAN的研究 是通过GAN 进行图像重建&#xff0c;恢复细节&#xff0c;去模糊&#xff0c;提高图像质量&#xff0c;图像还原&#xff0c;去噪等等。 识别相关 一种基于生成对抗网络的训练样本扩充…...

Flink-CDC——MySQL、SqlSqlServer、Oracle、达梦等数据库开启日志方法

目录 1. 前言 2. 数据源安装与配置 2.1 MySQL 2.1.1 安装 2.1.2 CDC 配置 2.2 Postgresql 2.2.1 安装 2.2.2 CDC 配置 2.3 Oracle 2.3.1 安装 2.3.2 CDC 配置 2.4 SQLServer 2.4.1 安装 2.4.2 CDC 配置 2.5达梦 2.4.1安装 2.4.2CDC配置 3. 验证 3.1 Flink版…...

linux设置tomcat redis开机自启动

设置Tomcat自启动 1.修改 /etc/rc.d/rc.local 文件 [rootiowZ]# vim /etc/rc.d/rc.local在/etc/rc.d/rc.local文件最后加上&#xff1a; export JAVA_HOME/usr/local/jdk /usr/local/apache-tomcat-8.5.73/bin/startup.sh start退出vim并保存修改的文件。 说明&#xff1a;/u…...

跨域问题讨论

问题 跨域定义 当一个请求url的协议、域名、端口三者之间任意一个与当前页面地址不同即为跨域。 跨域的安全隐患&#xff08;CSRF攻击&#xff09; 也就是说&#xff0c;一旦允许跨域&#xff0c;意味着允许恶意网站随意攻击可信网站&#xff0c;带来安全风险。 这里面有一…...

ESP32设备通信-两个ESP32设备之间HTTP通信

两个ESP32设备之间HTTP通信 文章目录 两个ESP32设备之间HTTP通信1、应用介绍2、软件准备3、硬件准备4、代码实现4.1 ESP32服务器节点代码4.2 ESP32客户端节点代码在本文中,我们将介绍如何在没有任何物理路由器或互联网连接的情况下使用 Wi-Fi 在两个 ESP32 开发板之间执行无线…...

数据结构学习笔记——查找算法中的树形查找(平衡二叉树)

目录 一、平衡二叉树的定义二、平衡因子三、平衡二叉树的插入和构造&#xff08;一&#xff09;LL型旋转&#xff08;二&#xff09;LR型旋转&#xff08;三&#xff09;RR型旋转&#xff08;四&#xff09;RL型旋转 四、平衡二叉树的删除&#xff08;一&#xff09;叶子结点&a…...

P1830 轰炸III

题目背景 一个大小为 &#xfffd;&#xfffd;nm 的城市遭到了 &#xfffd;x 次轰炸&#xff0c;每次都炸了一个每条边都与边界平行的矩形。 题目描述 在轰炸后&#xff0c;有 &#xfffd;y 个关键点&#xff0c;指挥官想知道&#xff0c;它们有没有受到过轰炸&#xff0c;如…...

大语言模型LLM知多少?

你知道哪些流行的大语言模型?你都体验过哪写? GPT-4,Llamma2, T5, BERT 还是 BART? 1.GPT-4 1.1.GPT-4 模型介绍 GPT-4(Generative Pre-trained Transformer 4)是由OpenAI开发的一种大型语言模型。GPT-4是前作GPT系列模型的进一步改进,旨在提高语言理解和生成的能力,…...

Redis命令行使用Lua脚本

Redis命令行使用Lua脚本 Lua脚本在Redis中的使用非常有用&#xff0c;它允许你在Redis服务器上执行自定义脚本&#xff0c;可以用于复杂的数据处理、原子性操作和执行多个Redis命令。以下是Lua脚本在Redis中的基本使用详细讲解&#xff1a; 运行Lua脚本&#xff1a; 在Redis中…...

HTML详细基础(三)表单控件

本帖介绍web开发中非常核心的标签——表格标签。 在日常我们使用到的各种需要输入用户信息的场景——如下图&#xff0c;均是通过表格标签table创造出来的&#xff1a; 目录 一.表格标签 二.表格属性 三.合并单元格 四.无序列表 五.有序列表 六.自定义标签 七.表单域 …...

map和set的具体用法 【C++】

文章目录 关联式容器键值对setset的定义方式set的使用 multisetmapmap的定义方式insertfinderase[]运算符重载map的迭代器遍历 multimap 关联式容器 关联式容器里面存储的是<key, value>结构的键值对&#xff0c;在数据检索时比序列式容器效率更高。比如&#xff1a;set…...

聚合统一,SpringBoot实现全局响应和全局异常处理

目录 前言 全局响应 数据规范 状态码(错误码) 全局响应类 使用 优化 全局异常处理 为什么需要全局异常处理 业务异常类 全局捕获 使用 优化 总结 前言 在悦享校园1.0版本中的数据返回采用了以Map对象返回的方式&#xff0c;虽然较为便捷但也带来一些问题。一是在…...

【C/C++笔试练习】——数组名和数组名、switch循环语句、数据在计算机中的存储顺序、字符串中找出连续最长的数字串、数组中出现次数超过一半的数字

文章目录 C/C笔试练习1.数组名和&数组名&#xff08;1&#xff09;数组名和&数组名的差异&#xff08;2&#xff09;理解数组名和指针偏移&#xff08;3&#xff09;理解数组名代表的含义&#xff08;4&#xff09;理解数组名代表的含义 2.switch循环语句&#xff08;6…...

力扣每日一题(+日常水题|树型dp)

740. 删除并获得点数 - 力扣&#xff08;LeetCode&#xff09; 简单分析一下: 每一个数字其实只有2个状态选 or 不 可得预处理每一个数初始状态(不选为0,选为所有x的个数 * x)累加即可 for(auto &x : nums)dp[x][1] x;每选一个树 i 删去 i 1 和 i - 1 故我们可以将 i…...

使用perming加速训练可预测的模型

监督学习模型的训练流程 perming是一个主要在支持CUDA加速的Windows操作系统上架构的机器学习算法&#xff0c;基于感知机模型来解决分布在欧式空间中线性不可分数据集的解决方案&#xff0c;是基于PyTorch中预定义的可调用函数&#xff0c;设计的一个面向大规模结构化数据集的…...

【数据库】存储引擎InnoDB、MyISAM、关系型数据库和非关系型数据库、如何执行一条SQL等重点知识汇总

目录 存储引擎InnoDB、MyISAM的适用场景 关系型和非关系型数据库的区别 MySQL如何执行一条SQL的 存储引擎InnoDB、MyISAM的适用场景 InnoDB 是 MySQL 默认的事务型存储引擎&#xff0c;只有在需要它不支持的特性时&#xff0c;才考虑使用其它存储引擎。实现了四个标准的隔…...

自动驾驶轨迹预测新思路:VectorNet如何用矢量编码替代传统栅格化方法?

自动驾驶轨迹预测的矢量革命&#xff1a;VectorNet如何重构环境编码范式 在自动驾驶系统的决策闭环中&#xff0c;轨迹预测模块犹如驾驶员的预判能力&#xff0c;其准确性直接关系到行车安全与舒适性。传统基于卷积神经网络&#xff08;CNN&#xff09;的预测方法存在一个根本性…...

MedGemma-X实战体验:像医生一样提问,AI智能回答

MedGemma-X实战体验&#xff1a;像医生一样提问&#xff0c;AI智能回答 1. 引言&#xff1a;当AI学会“看”和“说” 想象一下&#xff0c;你是一位放射科医生&#xff0c;面对一张复杂的胸部X光片&#xff0c;心中闪过几个疑问&#xff1a;“右肺中叶的阴影是炎症还是陈旧性…...

告别文档迁移困境:3个关键场景解锁飞书文档批量备份新方案

告别文档迁移困境&#xff1a;3个关键场景解锁飞书文档批量备份新方案 【免费下载链接】feishu-doc-export 项目地址: https://gitcode.com/gh_mirrors/fe/feishu-doc-export 还在为团队协作平台切换带来的文档迁移难题而烦恼吗&#xff1f;当企业从飞书切换到其他办公…...

ChatTTS 小说播音参数优化指南:如何实现自然流畅的语音合成

最近在做一个有声小说项目&#xff0c;尝试了多种语音合成方案&#xff0c;最终发现 ChatTTS 在中文小说播音的灵活性和自然度上表现相当不错。不过&#xff0c;刚上手时&#xff0c;直接使用默认参数生成的语音总感觉“味儿不对”&#xff0c;要么像机器人念稿&#xff0c;要么…...

MT5中文数据增强神器:无需训练,直接生成多样化的句子变体

MT5中文数据增强神器&#xff1a;无需训练&#xff0c;直接生成多样化的句子变体 1. 为什么需要中文文本数据增强 在自然语言处理领域&#xff0c;数据是模型训练的基础。但获取高质量的中文标注数据往往面临三大难题&#xff1a; 数据稀缺&#xff1a;特定领域&#xff08;…...

TranslucentTB:Windows任务栏透明化工具,让桌面视觉体验焕然一新

TranslucentTB&#xff1a;Windows任务栏透明化工具&#xff0c;让桌面视觉体验焕然一新 【免费下载链接】TranslucentTB A lightweight utility that makes the Windows taskbar translucent/transparent. 项目地址: https://gitcode.com/gh_mirrors/tr/TranslucentTB …...

构建高可用Chatbot UI完整模板:从架构设计到生产环境部署

痛点分析&#xff1a;Chatbot UI开发中的那些“坑” 在动手开发一个Chatbot UI之前&#xff0c;我们得先聊聊那些让开发者头疼的常见问题。如果你做过类似项目&#xff0c;下面这些场景一定不陌生&#xff1a; 状态管理失控&#xff1a;对话历史、用户输入、AI回复状态、连接…...

[特殊字符] Nano-Banana参数详解:LoRA权重对部件排布影响的实证分析

Nano-Banana参数详解&#xff1a;LoRA权重对部件排布影响的实证分析 1. 项目简介 Nano-Banana是一款专为产品拆解和平铺展示风格设计的轻量化文本生成图像系统。这个项目的核心价值在于深度融合了专属的Turbo LoRA微调权重&#xff0c;专门针对Knolling平铺、爆炸图、产品部件…...

PLECS 4.7模拟下的特斯拉Model 3电驱系统三步搭建与性能分析:从双闭环Boost电...

基于PLECS4.7的特斯拉Model3电驱仿真及报告 电驱系统仿真搭建过程&#xff0c;由三步构成&#xff0c;分别为&#xff1a;双闭环Boost电路搭建、三相逆变电路搭建&#xff0c;电机控制电路搭建。 双闭环Boost电路输入电压370V&#xff0c;输出电压为500V&#xff0c;实现50kW输…...

ChatTTS 自定义样本实战:如何高效构建个性化语音合成模型

最近在做一个需要个性化语音合成的项目&#xff0c;用到了ChatTTS。说实话&#xff0c;直接拿官方流程走自定义样本训练&#xff0c;那个效率真是让人有点头疼。数据准备繁琐&#xff0c;训练时间长&#xff0c;出来的效果还不一定稳定。经过一番折腾和优化&#xff0c;总算总结…...