【SpringCloud微服务项目实战-mall4cloud项目(4)】——mall4cloud-rbac

mall4cloud-rbac角色权限访问控制模块

  • 系统架构与模块介绍
    • 系统架构
    • rbac模型介绍
  • 相关代码
    • 权限校验
    • 接口代码
  • 补充

代码地址
github地址
fork自github原始项目
gitee地址
fork自gitee原始项目

系统架构与模块介绍

系统架构

在这里插入图片描述
从图中可以看到,微服务集群中,rbac模块是作为一个支持模块,与认证授权账户服务模块关联在一起的,但是代码中将其分离了出来作为单独的服务。中间的服务调用通过fegin来执行。对于权限管理系统来说,灵活而有组织的权限服务是必不可少的。

rbac模型介绍

RBAC(Role-Based Access Control)是一种访问控制模型,用于管理和控制系统或应用程序中的用户对资源的访问权限。RBAC基于角色的概念,将用户分配给不同的角色,而每个角色具有特定的权限,决定了用户可以执行的操作以及可以访问的资源。RBAC的主要组成部分包括:
User(用户):每个用户都有唯一的UID识别,并被授予不同的角色
Role(角色):不同角色具有不同的权限
Permission(权限):访问权限
用户-角色映射:用户和角色之间的映射关系
角色-权限映射:角色和权限之间的映射
可以通过以下关系反应

  1. 多用户对多角色关系: 多个用户可以被分配到一个或多个角色。这使得在一个组织中,不同用户可以担任不同的职务或角色,每个角色有不同的权限。
  2. 多角色对多权限关系: 多个角色可以包含一个或多个权限。这意味着不同的角色可以具有不同的权限,而同一权限可以分配给多个不同的角色。
    在这里插入图片描述
    上面的关系如果反应到数据库表设计中,至少需要五张表来设计:

用户表(User Table):用于存储系统中的用户信息,每个用户有唯一的标识符(用户ID)。
角色表(Role Table):用于存储不同角色的信息,每个角色也有唯一的标识符(角色ID)。
权限表(Permission Table):用于存储系统中各种权限的信息,每个权限也有唯一的标识符(权限ID)。
用户-角色关联表(User-Role Relationship Table):用于建立用户与角色之间的多对多关系,以确定哪些用户属于哪些角色。
角色-权限关联表(Role-Permission Relationship Table):用于建立角色与权限之间的多对多关系,以确定哪些角色有权执行哪些操作。

如果想在RBAC模型中增加一个菜单表,以管理系统菜单和其与角色的关联,可以将菜单表和角色-菜单关联表添加到数据库模型中
在系统的数据表中,分别对应了user(用户表),role(角色表),menu(菜单表)、menu_permission(菜单权限表,这里将菜单和权限结合)、user_role(用户角色关联表)、role_menu(角色菜单表)
在这里插入图片描述

相关代码

在模块中,主要是对于权限的校验是关联到了auth模块的过滤器中的代码,其他是提供到前端的接口代码

权限校验

auth模块下过滤器中代码如下:
在这里插入图片描述
在这里插入图片描述
①参数:传入了用户信息、uri、请求方式
②③:进行校验,主要是对普通用户端进行校验,其他没做校验,这里相当于只给了一个例子,有需要还是得自己补充。接下来就是调用rbac模块的远程接口。

在这里插入图片描述
①:查询用户拥有的权限标识集合,这里是三张表的关联查询。
在这里插入图片描述
②:根据用户类型获取权限对象
③④:判断逻辑为,如果请求的uri+method属于当前用户类型下的权限对象,判断这个用户下面的权限id集合是否包含该权限对象的id。包含则校验完成。

这里会有一个疑问,对每次的请求都去与数据库交互,会对性能造成影响。如果为了避免这个影响,可以通过使用缓存来存储已验证的权限结果,可以减少频繁校验的性能开销

代码中有这一步的处理:
在这里插入图片描述
在这里插入图片描述

通过使用@Cacheable进行了方法级别的缓存,同时还有使用@CacheEvict清理缓存(在每次登录后)

@Cacheable 是 Spring 框架提供的一个注解,用于启用方法级别的缓存。它可以用于将方法的计算结果缓存起来,以便在下一次调用相同方法时,可以直接返回缓存的结果,而不必重新计算
在使用时,需要配置缓存管理器。Spring 支持多个缓存管理器,例如 EhCache、Caffeine、Redis 等

缓存管理器的代码位置如下
在这里插入图片描述
具体代码如下:

package com.mall4j.cloud.common.cache.config;import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.mall4j.cloud.common.cache.adapter.CacheTtlAdapter;
import com.mall4j.cloud.common.cache.bo.CacheNameWithTtlBO;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;/*** @author FrozenWatermelon* @date 2020/7/4*/
@EnableCaching
@Configuration
public class RedisCacheConfig {@Beanpublic CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory, CacheTtlAdapter cacheTtlAdapter) {// 创建 RedisCacheManager 实例RedisCacheManager redisCacheManager = new RedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),// 默认策略,未配置的 key 会使用这个this.getRedisCacheConfigurationWithTtl(3600),// 指定 key 策略this.getRedisCacheConfigurationMap(cacheTtlAdapter));redisCacheManager.setTransactionAware(true);return redisCacheManager;}// 获取缓存策略的映射private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap(CacheTtlAdapter cacheTtlAdapter) {if (cacheTtlAdapter == null) {return Collections.emptyMap();}Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(16);// 根据 CacheTtlAdapter 配置每个缓存的超时时间for (CacheNameWithTtlBO cacheNameWithTtlBO : cacheTtlAdapter.listCacheNameWithTtl()) {redisCacheConfigurationMap.put(cacheNameWithTtlBO.getCacheName(),getRedisCacheConfigurationWithTtl(cacheNameWithTtlBO.getTtl()));}return redisCacheConfigurationMap;}// 获取 Redis 缓存策略(包括超时时间)private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.ofSeconds(seconds));return redisCacheConfiguration;}/*** 自定义redis序列化的机制,重新定义一个ObjectMapper.防止和MVC的冲突* https://juejin.im/post/5e869d426fb9a03c6148c97e*/@Beanpublic RedisSerializer<Object> redisSerializer() {ObjectMapper objectMapper = new ObjectMapper();// 反序列化时候遇到不匹配的属性并不抛出异常objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);// 序列化时候遇到空对象不抛出异常objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);// 反序列化的时候如果是无效子类型,不抛出异常objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);// 不使用默认的dateTime进行序列化,objectMapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false);// 使用JSR310提供的序列化类,里面包含了大量的JDK8时间序列化类objectMapper.registerModule(new JavaTimeModule());// 启用反序列化所需的类型信息,在属性中添加@classobjectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.PROPERTY);// 配置null值的序列化器GenericJackson2JsonRedisSerializer.registerNullValueSerializer(objectMapper, null);return new GenericJackson2JsonRedisSerializer(objectMapper);}@Beanpublic RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory,RedisSerializer<Object> redisSerializer) {RedisTemplate<Object, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);template.setDefaultSerializer(redisSerializer);template.setValueSerializer(redisSerializer);template.setHashValueSerializer(redisSerializer);template.setKeySerializer(StringRedisSerializer.UTF_8);template.setHashKeySerializer(StringRedisSerializer.UTF_8);template.afterPropertiesSet();return template;}@Beanpublic StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {return new StringRedisTemplate(redisConnectionFactory);}@Bean@ConditionalOnMissingBeanpublic CacheTtlAdapter cacheTtl() {return Collections::emptyList;}}

创建一个配置类,用于配置 Redis 缓存管理器。可以使用 @Configuration 注解和 @EnableCaching 注解来启用缓存,并配置 RedisCacheManager。RedisCacheManager是自定义的缓存策略。

this.getRedisCacheConfigurationMap(cacheTtlAdapter) 用于指定特定键的缓存策略。这是一种根据键的不同而使用不同策略的方式,可能根据不同的业务需求来自定义缓存超时时间等。cacheTtlAdapter 参数是一个用于生成特定键的策略的适配器。

@Bean 方法 cacheManager 创建了一个 Redis 缓存管理器 RedisCacheManager 的实例。这个管理器用于管理缓存,配置缓存的策略,以及连接到 Redis 数据库。在这个方法中,使用了以下关键配置:

RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory):创建了一个用于与 Redis 交互的 RedisCacheWriter,这里使用了非阻塞方式的写入。这是默认的并且常用的写入方式

getRedisCacheConfigurationWithTtl(3600):设置了默认的缓存策略,包括缓存超时时间为 3600 秒。

getRedisCacheConfigurationMap(cacheTtlAdapter):指定了特定键的缓存策略,这些策略根据不同的键和超时时间动态配置,通过 cacheTtlAdapter 获取。

setTransactionAware(true):设置缓存管理器为事务感知,以确保在事务中的缓存操作能够回滚。

getRedisCacheConfigurationMap 方法根据 cacheTtlAdapter 动态生成缓存策略的映射。这个方法会检查 cacheTtlAdapter 是否为 null,如果不是,则获取一组特定缓存键和对应的超时时间,并创建相应的缓存策略。如果 cacheTtlAdapter 为 null,则返回一个空的映射。

getRedisCacheConfigurationWithTtl 方法用于配置 Redis 缓存策略,包括序列化策略和缓存超时时间。

redisSerializer 方法创建了一个自定义的 Redis 数据序列化器,其中包含了一些自定义的配置,如序列化器失败时不抛出异常、处理空对象等。

redisTemplate 和 stringRedisTemplate 方法分别配置了 RedisTemplate 和 StringRedisTemplate,用于操作 Redis 数据库。它们使用了自定义的序列化器和连接工厂。

最后的 cacheTtl 方法用于创建一个缓存超时时间适配器 CacheTtlAdapter,默认情况下返回一个空列表。

接口代码

接口代码主要从controller看即可,都是相关的一些数据表的业务需求,这里不再过多赘述
在这里插入图片描述

补充

关于rbac的一些扩展

RBAC1 模型
在 RBAC的基础上引入了角色继承的概念。即:子角色可以继承父角色的所有权限。
使用场景:如某个业务部门,有经理、主管、专员。主管的权限不能大于经理,专员的权限不能大于主管,如果采用 RBAC0 模型做权限系统,极可能出现分配权限失误,最终出现主管拥有经理都没有的权限的情况。
而 RBAC1 模型就很好解决了这个问题,创建完经理角色并配置好权限后,主管角色的权限继承经理角色的权限,并且支持在经理权限上删减主管权限

关于权限管理系统
若依权限管理系统也是一个适合学习的项目,代码地址:https://gitee.com/y_project/RuoYi-Cloud
RuoYi-Cloud

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

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

相关文章

03 里氏替换原则

官方定义&#xff1a; 里氏替换原则&#xff08;Liskov Substitution Principle&#xff0c;LSP&#xff09;是由麻省理工学院计算机科学系教授芭芭拉利斯科夫于 1987 年在“面向对象技术的高峰会议”&#xff08;OOPSLA&#xff09;上发表的一篇论文《数据抽象和层次》&#…

『Linux升级路』基本指令

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;Linux &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、认识操作系统 &#x1f4d2;1.1什么是操作系统 &#x1f4d2;1.2操作系统…

如何处理前端路由懒加载?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

js实现红包雨功能(canvas,react,ts),包括图片不规则旋转、大小、转速、掉落速度控制、屏幕最大红包数量控制等功能

介绍 本文功能由canvas实现红包雨功能&#xff08;index.tsx&#xff09;本文为react的ts版。如有其他版本需求可评论区观赏地址&#xff0c;需过墙 import React, { Component } from react; // import ./index.css; import moneyx from /assets/images/RedEnvelopeRain/bal…

算水质TDS加温度补偿

先上图&#xff0c;就图里这款水质检测&#xff0c;用树莓派3/4的话&#xff0c;要配个温度检测作为温度校正&#xff0c;以及一个adc 元器件。我选ds18b20和ads1115。 再把模拟数据计算过程放一下&#xff1a; 温度检测元器件在农历钟那里提过&#xff0c;就是同款。此处先测个…

Android11 移植memtester压测内存

需求如题&#xff0c;从网上下载了memtest源码压缩包&#xff0c;准备放到系统源码编译&#xff0c;然后push到板子上执行&#xff0c;结果&#xff0c;编译出来一堆问题&#xff0c;报build err。 做如下代码改动&#xff1a; external/memtester-4.5.1/Android.mk | 16 exte…

机器学习基础之《回归与聚类算法(4)—逻辑回归与二分类(分类算法)》

一、什么是逻辑回归 1、逻辑回归&#xff08;Logistic Regression&#xff09;是机器学习中的一种分类模型&#xff0c;逻辑回归是一种分类算法&#xff0c;虽然名字中带有回归&#xff0c;但是它与回归之间有一定的联系。由于算法的简单和高效&#xff0c;在实际中应用非常广…

使用cpolar内网端口映射技术实现U8用友ERP本地部署的异地访问

文章目录 前言1. 服务器本机安装U8并调试设置2. 用友U8借助cpolar实现企业远程办公2.1 在被控端电脑上&#xff0c;点击开始菜单栏&#xff0c;打开设置——系统2.2 找到远程桌面2.3 启用远程桌面 3. 安装cpolar内网穿透3.1 注册cpolar账号3.2 下载cpolar客户端 4. 获取远程桌面…

NTFS磁盘格式读写工具Tuxera NTFS 2023 for Mac中文破解版v2023含最新激活序列号

Tuxera NTFS 2023 Mac 是一个NTFS文件系统驱动程序&#xff0c;为解决Mac上不能对NTFS格式硬盘进行访问和读写而生。实现苹果Mac OS X系统读写Microsoft Windows NTFS文件系统&#xff0c;在硬盘、U盘等外接设备中进行全面访问、删除、修改等相关操作。 tuxera ntfs 2023 破解…

Web架构安全分析/http/URL/Cookie攻击

Web 架构安全分析 Web 工作机制及基本概念 传统 Web 架构 LAMP 网页 概念 网页就是我们可以通过浏览器上网看到的精美页面&#xff0c;一般都是经过浏览器渲染过的 .html 页面&#xff0c;html 语言在浏览器中渲染。其中包含了CSS、JavaScript 等前端技术。通过浏览器访问…

24届好未来数开笔试

目录 选择、多选SQL题目描述输入 目标解答解析 题目分享 选择、多选 Java, int x 1, float y 2, x/y 0.5 2. Hive 的数据结构 基本数据类型 复合数据类型 text 不是 Hive 内外表 建表时如果不显示声明表的类型为 外表 Kafka 通过&#xff08;&#xff09;避免任务重复执行…

【技巧】如何设置Excel表只输入固定内容?

如果你需要在Excel表格中输入固定的内容&#xff0c;可以设置“限制录入内容”&#xff0c;这样就只能输入设置好的内容&#xff0c;避免不小心输入错误信息。下面来看看如何设置吧。 首先&#xff0c;打开Excel表格后&#xff0c;选中需要输入固定内容的表格区域。 比如图片…

Flutter笔记:发布一个Flutter头像模块 easy_avatar

Flutter笔记 发布一个头像Flutter模块 easy_avatar 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/1339…

利用PHP快速抓取音频数据的方法与技巧

目录 使用cURL库抓取音频数据 优点 潜在问题及解决方案 使用file_get_contents函数抓取音频数据 优点 潜在问题及解决方案 总结 随着互联网的发展&#xff0c;音频内容在网络上的应用越来越广泛&#xff0c;如音乐播放、语音通信等。有时&#xff0c;我们需要从特定的音…

ModStartCMS v7.4.0 公共图片库支持,安全功能升级

ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议&#xff0c;免费且不限制商业使用。 功能特性 丰富的模块市…

【Linux-常用命令-基础命令-删除文件夹以及内容-rm--r-命令-笔记】

【Linux-常用命令-基础命令-删除文件夹以及内容-rm--r-命令-笔记】 1、前言2、操作3、自己的操作 1、前言 最近&#xff0c;在使用Linux的时&#xff0c;使用相关基础命令是&#xff0c;总是容易忘记&#xff0c;上网一搜&#xff0c;大部分都写的比较繁琐&#xff0c;关于删除…

Python学习笔记——存储容器

食用说明&#xff1a;本笔记适用于有一定编程基础的伙伴们。希望有助于各位&#xff01; 列表 列表类似数组&#xff0c;其中可以包含不同类型的元素&#xff0c;写法如下&#xff1a; list1 [Google, Runoob, 1997, 2000] list2 [1, 2, 3, 4, 5 ] list3 ["a", …

Qt工具开发,该不该跳槽?

Qt工具开发&#xff0c;该不该跳槽? 就这样吧&#xff0c;我怕你跳不动。 嵌入式UI&#xff0c;目前趋势是向着LVGL发展。QT已经在淘汰期了。很多项目还在用&#xff0c;但技术上已经落后。QT短期内不会全面淘汰&#xff0c;但退位让贤的大趋势已经很清楚了。 最近很多小伙伴…

liunx下软链接和硬链接的用法

什么是软链接&#xff08;类似快捷方式&#xff09;&#xff1a; 符号连接&#xff08;Symbolic Link&#xff09;&#xff0c;也叫软连接。 软链接文件有类似于 Windows 的快捷方式。它实际上是一个特殊的文件。在符号连接中&#xff0c;文件实际上是一个文本文件&#xff0c…

嵌入式开发学习之STM32F407串口(USART)收发数据(三)

嵌入式开发学习之STM32F407串口&#xff08;USART&#xff09;收发数据&#xff08;三&#xff09; 开发涉及工具一、选定所使用的串口二、配置串口1.配置串口的I/O2.配置串口参数属性3.配置串口中断4.串口中断在哪里处理5.串口如何发送字符串 三、封装串口配置库文件1.创建头文…