RBAC 动态权限

文章目录

  • 前言
  • 一、RBAC(Role-Based Access Control,基于角色的访问控制)
  • 二、Java实现RBAC 权限的大概思路
      • 1. 添加依赖
      • 2. 配置MyBatis-Plus和数据源
        • 1. 添加依赖
        • 2. 实体类与Mapper接口
        • UserMapper.java
      • 3. 配置MyBatis-Plus
        • 4. 自定义UserDetailsService
      • 3. 实体和Mapper
        • 数据库表设计
        • JPA实体映射示例
        • 注意
      • 4. 实现UserDetailsService
      • 5. JWT过滤器和认证逻辑
      • 6. Spring Security配置
      • 示例代码片段
        • JWT工具类
        • JWT过滤器
        • Spring Security配置
      • 7. 登录API实现


前言

前端学java,用于记录学习,AI辅助创作,有错误之处,欢迎交流指正。👏🏻

一、RBAC(Role-Based Access Control,基于角色的访问控制)

RBAC(Role-Based Access Control,基于角色的访问控制)是一种流行的权限管理模型,它通过角色作为用户与权限之间的中介,实现了权限的灵活管理和动态分配。以下是RBAC动态权限控制的关键概念和特点:

基本元素:

用户(User):系统中的操作者,可以是员工、客户等。
角色(Role):一组权限的集合,定义了用户可以执行的操作。角色是根据业务需求和职责划分创建的,如管理员、编辑、访客等。
权限(Permission):系统中定义的具体操作权利,如读取文件、写入数据库、删除记录等。
动态权限控制的特点:

灵活性:用户与权限之间不直接关联,而是通过角色作为中间层。当用户的角色发生变化时,其权限随之改变,无需逐一调整用户权限,提高了管理效率。
细粒度控制:允许为角色分配具体的权限,实现对系统资源访问的细粒度管理。
易于维护:角色的增删改直接影响相关用户的权限,简化了权限调整的过程,便于大规模系统的权限管理。
权限继承与组合:可以定义角色之间的继承关系,或者组合多个角色赋予单个用户,以适应复杂的权限需求。
实时性:动态权限控制意味着权限更改可以即时生效,无需重启服务或重新登录,增强了系统的实时响应能力。
实现机制:

权限检查:每次用户尝试访问资源或执行操作时,系统都会检查用户所属角色是否有对应权限。
权限缓存:为了提高性能,通常会将权限信息缓存起来,减少数据库的频繁访问。
动态加载:权限配置可以在运行时动态加载和更新,无需重启应用即可调整权限策略。
API网关与过滤器:在微服务架构中,常利用API网关或在服务内部设置权限过滤器来实现动态权限验证。
综上所述,RBAC动态权限控制通过引入角色作为中间层,实现了用户权限的灵活配置和高效管理,是现代复杂系统中常见的权限管理模式。

二、Java实现RBAC 权限的大概思路

要在Java Spring Boot项目中结合Spring Security实现RBAC权限控制,并使用MyBatis-Plus作为ORM工具以及JWT进行登录认证,可以遵循以下步骤:

1. 添加依赖

pom.xml中添加Spring Security、MyBatis-Plus和JWT相关的依赖:

<dependencies><!-- Spring Security --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.2</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.2</version><scope>runtime</scope></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.11.2</version><scope>runtime</scope></dependency><!-- MyBatis-Plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.x.x</version></dependency>
</dependencies>

2. 配置MyBatis-Plus和数据源

使用MyBatis-Plus作为ORM工具可以简化MyBatis的使用,提供更多的开箱即用的功能,如自动分页、性能优化等。下面是使用MyBatis-Plus实现上述RBAC模型的示例。

1. 添加依赖

首先,在项目的pom.xml中添加MyBatis-Plus的依赖:

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.x.x</version> <!-- 使用最新版本 -->
</dependency>
2. 实体类与Mapper接口

实体类保持不变,依然是之前的User, Role, Permission。接下来,使用MyBatis-Plus的BaseMapper接口来简化Mapper的编写。

UserMapper.java
import com.baomidou.mybatisplus.core.mapper.BaseMapper;public interface UserMapper extends BaseMapper<User> {// 如果有特殊的查询需求,可以在这里添加自定义方法
}

同理,为RolePermission创建类似的Mapper接口:

public interface RoleMapper extends BaseMapper<Role> {
}public interface PermissionMapper extends BaseMapper<Permission> {
}

3. 配置MyBatis-Plus

在Spring Boot的配置文件application.ymlapplication.properties中配置MyBatis-Plus和数据源:

mybatis-plus:global-config:db-config:id-type: autoconfiguration:map-underscore-to-camel-case: true # 开启下划线转驼峰命名规则mapper-locations: classpath:mapper/*.xml # 如果有自定义的XML映射文件,需要配置此路径spring:datasource:url: jdbc:mysql://localhost:3306/your_db?useSSL=false&serverTimezone=UTCusername: your_usernamepassword: your_passworddriver-class-name: com.mysql.cj.jdbc.Driver
4. 自定义UserDetailsService

由于MyBatis-Plus已经简化了数据访问层的操作,我们可以直接在MyUserDetailsService中使用BaseMapper来查询用户及其关联的角色和权限:

@Service
public class MyUserDetailsService implements UserDetailsService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate RoleMapper roleMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));if (user == null) {throw new UsernameNotFoundException("User not found with username: " + username);}List<GrantedAuthority> authorities = new ArrayList<>();List<Role> roles = userMapper.selectRolesByUserId(user.getId());for (Role role : roles) {authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));// 通常情况下,权限也会通过角色间接关联,这里简化处理}return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);}
}

注意,上述示例中selectRolesByUserId方法假设是自定义扩展的,因为MyBatis-Plus的BaseMapper默认不会包含多表关联查询。如果需要这样的关联查询,你可以:

  • 直接在Mapper接口中定义该方法并编写对应的SQL(推荐使用注解形式)。
  • 或者,如果复杂度高,可以在Mapper接口中声明方法,然后在对应的XML文件中编写SQL查询。

使用MyBatis-Plus可以大大减少模板代码,提升开发效率,但依然需要根据具体需求灵活定制SQL查询逻辑。

3. 实体和Mapper

定义用户、角色、权限的实体类及对应的MyBatis-Plus Mapper接口,如之前讨论的那样。

为了实现RBAC模型,我们通常需要设计至少三张数据库表:用户表(users)、角色表(roles)和权限表(permissions),以及一张关联表(user_roles)来关联用户与角色,另一张关联表(role_permissions)来关联角色与权限。下面是这些表的一个简单设计示例,以及如何使用JPA进行映射。

数据库表设计
  1. users 表:

    • id (主键)
    • username (用户名)
    • password (密码,通常存储的是哈希值)
  2. roles 表:

    • id (主键)
    • name (角色名,如"ADMIN", “USER”)
  3. permissions 表:

    • id (主键)
    • name (权限名,如"READ", “WRITE”)
  4. user_roles 表(多对多关联表):

    • user_id (外键,关联users表的id)
    • role_id (外键,关联roles表的id)
  5. role_permissions 表(多对多关联表):

    • role_id (外键,关联roles表的id)
    • permission_id (外键,关联permissions表的id)
JPA实体映射示例

以下是如何使用Spring Data JPA映射这些实体的例子:

@Entity
@Table(name = "users")
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String username;private String password; // 应使用BCrypt等加密存储@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)@JoinTable(name = "user_roles",joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))private Set<Role> roles;// 构造函数、getter、setter省略
}@Entity
@Table(name = "roles")
public class Role {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;@ManyToMany(mappedBy = "roles")private Set<User> users;@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)@JoinTable(name = "role_permissions",joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"),inverseJoinColumns = @JoinColumn(name = "permission_id", referencedColumnName = "id"))private Set<Permission> permissions;// 构造函数、getter、setter省略
}@Entity
@Table(name = "permissions")
public class Permission {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;@ManyToMany(mappedBy = "permissions")private Set<Role> roles;// 构造函数、getter、setter省略
}
注意
  • 上述代码中,实体间的关联关系使用了@ManyToMany注解,并通过@JoinTable指定了关联表的细节。
  • fetch = FetchType.EAGER表示关联数据会立即加载,根据实际情况也可以设置为LAZY延迟加载。
  • 在实际应用中,密码字段应该使用密码加密器(如BCrypt)处理后再存储,而不是明文。
  • 还需实现UserDetailsService接口时,利用上述实体直接从数据库加载用户信息,包括其关联的角色和权限。

通过这种方式,你可以有效地在Spring Security框架内实现基于角色的访问控制,并利用数据库来持久化这些信息。

4. 实现UserDetailsService

创建自定义的UserDetailsService,使用MyBatis-Plus查询用户信息,并转换为Spring Security的UserDetails对象。

5. JWT过滤器和认证逻辑

  • 创建一个JWT Token生成和解析的工具类。
  • 实现一个JWT过滤器(继承自OncePerRequestFilter),用于解析请求头中的JWT令牌,验证用户身份,并设置认证信息到Security上下文中。
  • 实现登录逻辑,验证用户名和密码后,使用JWT工具类生成Token并返回给客户端。

6. Spring Security配置

  • 配置Spring Security,禁用默认的表单登录,添加JWT过滤器到过滤链中。
  • 定义访问控制规则,使用@PreAuthorize@PostAuthorize等注解在Controller的方法上实现细粒度的权限控制,或者在Spring Security配置类中使用.authorizeRequests()来配置URL访问规则。

示例代码片段

JWT工具类
public class JwtTokenProvider {// 使用密钥生成Token的逻辑// 验证Token的逻辑
}
JWT过滤器
public class JwtAuthenticationFilter extends OncePerRequestFilter {// 实现JWT的解析与用户认证逻辑
}
Spring Security配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate JwtAuthenticationFilter jwtAuthenticationFilter;@Overrideprotected void configure(HttpSecurity http) throws Exception {http = http.csrf().disable();http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class).authorizeRequests().antMatchers("/login").permitAll().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasAnyRole("USER", "ADMIN").anyRequest().authenticated();}
}

7. 登录API实现

创建一个登录接口,接收用户名和密码,验证后生成JWT并返回。

以上步骤概括了使用Spring Security、MyBatis-Plus和JWT实现RBAC权限控制的基本流程。根据实际项目需求,可能还需要进一步细化和调整。


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

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

相关文章

民国漫画杂志《时代漫画》第15期.PDF

时代漫画15.PDF: https://url03.ctfile.com/f/1779803-1247458444-8befd8?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了&#xff0c;截止1937年6月战争来临被迫停刊共发行了39期。 ps:资源来源网络&#xff01;

【LeetCode:2769. 找出最大的可达成数字 + 模拟】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Nodejs(文件操作,构建服务器,express,npm)

文章目录 文件操作1.读取文件1&#xff09;步骤2&#xff09;范例 2.写文件1&#xff09;步骤2&#xff09;范例 3.删除文件4.重命名文件夹5删除文件夹 Url1.url.parse()2.url.fomat() Query1.query.parse()2.query.stringfy()3.编码和解码 第三方模块1.nodemailer2.body-parse…

BUUCTF-Misc24

从娃娃抓起1 1.打开附件 是两个文本文件 2.电报码 电报码在线翻译网站&#xff1a;https://usetoolbar.com/convert/cccn.html 3.汉字五笔编码 汉字五笔编码在线网站查询&#xff1a;https://www.qqxiuzi.cn/bianma/wubi.php 4.转化为MD5值 将文字保存到文本文档 用winR输入…

部署ELK日志分析系统——超详细

ELK日志分析系统 文章目录 ELK日志分析系统资源列表基础环境一、环境准备二、部署Elasticsearch软件2.1、安装Elasticsearch软件2.2、加载系统服务2.3、更改Elasticsearch主配置文件2.4、创建数据存放路径并授权2.5、启动Elasticsearch2.6、查看节点信息 三、安装Elasticsearch…

PDF转word 免费软件推荐

超级PDF 免费的 PDF转Word|在线免费PDF转Word - 超级PDF 知乎推荐&#xff0c;还没试用&#xff1a; https://zhuanlan.zhihu.com/p/614750512?utm_id0

【WEEK13】 【DAY5】Shiro第五部分【中文版】

2024.5.24 Friday 接上文【WEEK13】 【DAY4】Shiro第四部分【中文版】 目录 15.7.Shiro请求授权的实现15.7.1.修改ShiroConfig.java15.7.1.1.添加一行验证授权的代码15.7.1.2.重启 15.7.2.修改MyController.java15.7.3.修改ShiroConfig.java15.7.4.重启15.7.5.修改UserRealm.ja…

Jenkins 动态salve简单配置连接 EKS

安装Jenkins helm repo add jenkins https://charts.jenkins.io helm repo update # 当前版本 jenkins-5.1.18.tgz瘦身后的 values.yaml # grep -Ev ^\s*#|^$ values.yaml nameOverride: fullnameOverride: namespaceOverride: clusterZone: "cluster.local" kubern…

C#对文件进行批量重命名或者对某个单独的文件进行改名

目录 一、FolderBrowserDialog 二、OpenFileDialog 三、Path 四、ui设计 五、代码部分 一、FolderBrowserDialog FolderBrowserDialog是一个用于选择文件夹的对话框控件&#xff0c;可以在windows Forms应用程序中使用。使用它可以让用户选择一个文件夹&#xff0c;并返…

Kubernetes 之硬盘持久化和 EmptyDir 与 HostPath 挂载类型

Kubernetes 之硬盘持久化和 EmptyDir 与 HostPath 挂载类型 持久化存储的意义 在 Kubernetes 中部署的应用都是以 Pod 的方式运行的。大部分情况这些 Pod 是无状态的。但是假如我们部署数据库或者需要一个存放关键文件的文件夹的时候&#xff0c;这时候我们就需要存储持久化以…

ShardingSphere如何完成与Spring家族无缝整合的?

系统集成即ShardingSphere 和 Spring 框架的集成。 ShardingSphere 实现两种系统集成机制&#xff1a; 命名空间&#xff08;namespace&#xff09;机制&#xff0c;通过扩展 Spring Schema 来实现与 Spring 框架的集成编写自定义 starter 组件完成与 Spring Boot 的集成 1 …

需求:实现一个可以统计代码的运行时间

需求&#xff1a;有一个做加法计算的函数&#xff0c;要统计执行这个加法函数代码运行了多久 import timedef add(a, b):time.sleep(1)return a bst time.time() add(100, 200) et time.time() print("该函数运行时间为&#xff1a;", et - st) 学了闭包&#x…

文件批量替换

替换yaml文件中的kube-system成ck find . -type f -name "*.yaml" -exec sed -i s/kube-system/ck/g {} \;

实现C++ Stack(顺序栈)

参考QStack&#xff0c;继承自Vector 类声明 template<typename T>class Stack :protected Vector<T>{public:explicit Stack()noexcept;Stack(const Stack&t)noexcept;Stack(Stack&&t)noexcept;Stack& operator (const Stack& t)noexcept;S…

C#面:请解释转发与跳转的区别

在C#中&#xff0c;转发&#xff08;forwarding&#xff09;和跳转&#xff08;jumping&#xff09;是两种不同的控制流程操作。 转发 是指将控制权从一个方法或函数转移到另一个方法或函数。在转发中&#xff0c;程序会将当前的执行状态传递给另一个方法&#xff0c;并在该方…

【EventSource错误解决方案】设置Proxy后SSE发送的数据只在最后接收到一次,并且数据被合并

【EventSource错误解决方案】设置Proxy后SSE发送的数据只在最后接收到一次&#xff0c;并且数据被合并 出错描述 出错原因与解决方案 出错描述 SSE前后端一切正常&#xff0c;但是fetchEventSource 的onmessage回调函数只在所有流都发送完毕后&#xff0c;才会执行一次。 前…

【编译原理复习笔记】中间语言

中间语言 中间语言的特点和作用 &#xff08;1&#xff09;独立于机器 &#xff08;2&#xff09;复杂性介于源语言和目标语言之间 中间语言可以使编译程序的结构在逻辑上更为简单明确 常用的中间语言 后缀式 图表示&#xff1a;抽象语法树&#xff0c;有向无环图 三地址代…

Elasticsearch的复制功能

Elasticsearch的复制功能 Elasticsearch的复制功能确保了数据的高可用性和耐久性。当一个节点临时下线&#xff0c;其上承载的主分片&#xff08;primary shards&#xff09;将不可用。但是&#xff0c;副本分片&#xff08;replica shards&#xff09;会继续提供服务。以下是…

【软件设计师】先导

一、考试科目&#xff1a; 上午&#xff1a;计算机与软件工程知识&#xff0c;考试时间150min&#xff0c;75空单选题&#xff08;不一定一题一空&#xff09; 下午&#xff1a;软件设计&#xff0c;考试时间150分钟&#xff0c;问答题&#xff0c;6道只做5大题&#xff08;前四…

【论文阅读】Prompt Fuzzing for Fuzz Driver Generation

文章目录 摘要一、介绍二、设计2.1、总览2.2、指导程序生成2.3、错误程序净化2.3.1、执行过程净化2.3.2、模糊净化2.3.3、覆盖净化 2.4、覆盖引导的突变2.4.1、功率调度2.4.2、变异策略 2.5、约束Fuzzer融合2.5.1、论据约束推理2.5.1、模糊驱动融合 三、评估3.1、与Hopper和OSS…