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

news2024/11/18 1:40:48

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 {

	@Bean
	public 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
	 */
	@Bean
	public 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());
		// 启用反序列化所需的类型信息,在属性中添加@class
		objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL,
				JsonTypeInfo.As.PROPERTY);
		// 配置null值的序列化器
		GenericJackson2JsonRedisSerializer.registerNullValueSerializer(objectMapper, null);
		return new GenericJackson2JsonRedisSerializer(objectMapper);
	}

	@Bean
	public 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;
	}

	@Bean
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
		return new StringRedisTemplate(redisConnectionFactory);
	}

	@Bean
	@ConditionalOnMissingBean
	public 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.coloradmin.cn/o/1106196.html

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

相关文章

Netty系列教程之NIO基础知识

近30集的孙哥视频课程&#xff0c;看完一集整理一集来的&#xff0c;内容有点多&#xff0c;请大家放心食用~ 1. 网络通讯的演变 1.1 多线程版网络通讯 在传统的开发模式中&#xff0c;客户端发起一个 HTTP 请求的过程就是建立一个 socket 通信的过程&#xff0c;服务端在建立…

直线导轨在喷涂行业中的应用场景

直线导轨因其具有精度高、速度快、刚性强、使用寿命长等特点被广泛应用在各行各种中&#xff0c;其中&#xff0c;在喷涂行业中的应用最为广泛&#xff0c;以下是直线导轨在喷涂行业中的应用场景&#xff1a; 1、平面喷涂&#xff1a;直线导轨可以应用在各种机械加工的平面&…

将Sketch文件转化为PSD文件的简单在线工具!

设计工作不仅需要UI设计工具&#xff0c;还需要Photoshop。常见的UI设计工具Sketch与Photoshop软件不兼容。如果你想在实际工作中完成Sketch转psd&#xff0c;你需要使用其他软件进行转换。但是在转换过程中容易丢失文件&#xff0c;导致同样的工作需要重复多次才能完成&#x…

图论相关算法

一、迪杰斯特拉(Dijkstra)算法 迪杰斯特拉算法使用类似广度优先搜索的方法解决了带权图的单源最短路径问题。这是一个贪心算法。 1.核心思想 &#xff08;1&#xff09;每次选中一个点&#xff0c;这个点满足两个条件&#xff1a; 未被选过距离最短 &#xff08;2&#xf…

Gazebo仿真 【ROS: noetic】

参考链接&#xff1a;《ROS机器人开发实践》_胡春旭 目标&#xff1a; 了解如何使用URDF文件创建一个机器人模型&#xff0c;然后使用xacro文件优化该模型&#xff0c;并且放置到rvizArbotiX或Gazebo仿真环境中&#xff0c;以实现丰富的ROS功能。 4.5 Gazebo仿真环境 1&#x…

kaggle新赛:UBC卵巢癌亚型分类和异常检测大赛【图像分类】

赛题名称&#xff1a;UBC Ovarian Cancer Subtype Classification and Outlier Detection (UBC-OCEAN) 赛题链接&#xff1a;https://www.kaggle.com/competitions/UBC-OCEAN 赛题背景 卵巢癌是女性生殖系统最致命的癌症。目前&#xff0c;卵巢癌诊断依赖病理学家评估亚型。…

MySQL的自增id会用完吗?用完怎么办?

MySQL作为最常用的关系型数据库&#xff0c;无论是在应用还是在面试中都是必须掌握的技能。 目录 一、MySQL自增主键会用完吗 二、MySQL自增主键用完会怎样 1.程序员自己设置的自增主键 2.程序员没有设置自增主键&#xff0c;mysql自动创建row_id 三、mysql中还有哪些自增…

IF: 22.1, 中科院1区TOP刊被剔除WOS (10月SCI/SSCI目录已更新)~

2023年10月17日&#xff0c;科睿唯安更新了Web of Science核心期刊目录。 此次更新后SCIE期刊目录共包含9485本期刊&#xff0c;SSCI期刊目录共包含3551本期刊。此次SCIE & SSCI期刊目录更新&#xff0c;与上次更新&#xff08;2023年9月&#xff09;相比&#xff0c;共有7…

电子期刊制作宝典,让你成为专业行家

电子期刊作为一种新兴的媒体形式&#xff0c;越来越受到人们的喜爱。它不仅方便快捷&#xff0c;而且可以随时随地阅读&#xff0c;不受时间和空间的限制。那么&#xff0c;如何制作一份高质量的电子期刊呢&#xff1f; 1.首先打开FLBOOK电子杂志平台 2.然后点击模板选择电子期…

springBoot--web开发--WebMvcAutoConfiguration原理

WebMvcAutoConfiguration原理 自动配置类的生效条件hiddenHttpMethodFilter和formContentFilter的作用WebMvcConfigurer的作用 自动配置类的生效条件 点击ctarln 搜索类WebMvcAutoConfiguration hiddenHttpMethodFilter和formContentFilter的作用 hiddenHttpMethodFilter&am…

CLIP模型原理

CLIP模型 CLIP(Contrastive Language-Image Pre-Training) 模型是 OpenAI 在 2021 年初发布的用于匹配图像和文本的预训练神经网络模型&#xff0c;是近年来在多模态研究领域的经典之作。OpenAI 收集了 4 亿对图像文本对&#xff08;一张图像和它对应的文本描述&#xff09;&a…

UPS设备的最新管理方法,简单高效!

随着信息技术的快速发展&#xff0c;UPS监控系统变得至关重要。系统用于监视、管理和维护机房中的UPS设备&#xff0c;以确保稳定的电力供应&#xff0c;保护敏感的电子设备和数据中心运营。 UPS监控系统提供了对电力系统的关键可见性&#xff0c;使运维团队能够预测和解决潜在…

家政系统预约小程序具备哪些功能?

预约家政小程序有这么大的市场需求加上这么多的好处&#xff0c;相信未来发展前景不错。也必将吸引很多商家投资者着手开发属于自己的上门家政APP小程序软件&#xff0c;在实际的开发过程中需要具备哪些功能呢&#xff1f; 一、用户端功能&#xff1a; 1. 用户注册登录&#x…

绕过防火墙

1.pikuchu靶场 位置 该文件 然后找到install 文件 初始化 创建 就ok了 安全狗搭建 bug解决 进入apache目录 命令 安全狗安装 重启web服务 绕过 前端 绕过 waf 阻拦 脏数据 成功 二.yakit 中国版的bp

源码编译安装部署lnmp

源码编译安装部署lnmp 文章目录 源码编译安装部署lnmp1.简介&#xff1a;2.环境说明&#xff1a;3.部署前的准备工作4.安装nginx4.1.进入官网拉取nginx源码包4.2.通过IP地址访问nginx的web页面 5.安装mysql5.1.安装依赖包5.2.创建用户和组5.3.下载源码包并解压到/usr/local/5.4…

在数组中合并相同id数据,并且数据中某一字段不一致也统一合并进去

封装的合并的函数 function formateArray(data:any){// ts-ignorelet res data.reduce((ac,a) > {// ts-ignorelet index ac.findIndex(x > x.id a.id);index -1 ? ac.push({...a}) : ac[index] {...ac[index],...a};return ac;},[])return res;}使用 allData 原始…

忆联分布式数据库存储解决方案,助力MySQL实现高性能、低时延

据艾瑞咨询研究院《2022 年中国数据库研究报告》显示&#xff0c;截止2021年&#xff0c;中国分布式数据库占比达到 20%左右&#xff0c;主要以 MySQL 和 PostgreSQL 为代表的开源数据库为主。MySQL 作为备受欢迎的开源数据库&#xff0c;当前已广泛应用于互联网、金融、交通、…

(Python)在Matplotlib中对图像坐标轴进行log转换

对于跨度很大其分布离散的数据&#xff0c;常用log转换来缩写其差距&#xff0c;呈现在图上的效果也更好&#xff0c;比如在绘制转录组的表达量数据时&#xff0c;常用log转换之后的值进行绘制。在matplotlib中&#xff0c;支持在绘图时对数据进行log转换&#xff0c;根据log转…

解密代理IP:加速互联网业务的利器

众所周知&#xff0c;代理IP是一类常见的互联网服务。借助代理IP&#xff0c;一个终端可以通过远程的服务器&#xff08;即代理IP对应的服务器&#xff09;访问另一个终端&#xff0c;从而非直接地接触。代理IP在日常互联网应用中的应用场景十分广泛&#xff0c;包括但不限于&a…

C++:模板初阶

本篇文章主要对模板有个简单的认识&#xff0c;方便我们后面对模板进行更加深入的学习。 目录 1.泛型编程 2.函数模板 2.1 函数模板的概念 2.2 函数模板格式 2.3 函数模板的原理 2.4 函数模板的实例化 2.5 模板参数的匹配原则 3.类模板 3.1 类模板的格式定义 3.2 类模…