RBAC 动态权限

2024-05-27 01:52
文章标签 动态 权限 rbac

本文主要是介绍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权限控制的基本流程。根据实际项目需求,可能还需要进一步细化和调整。


这篇关于RBAC 动态权限的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1006202

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

浅析如何使用Swagger生成带权限控制的API文档

《浅析如何使用Swagger生成带权限控制的API文档》当涉及到权限控制时,如何生成既安全又详细的API文档就成了一个关键问题,所以这篇文章小编就来和大家好好聊聊如何用Swagger来生成带有... 目录准备工作配置 Swagger权限控制给 API 加上权限注解查看文档注意事项在咱们的开发工作里,API

Java使用POI-TL和JFreeChart动态生成Word报告

《Java使用POI-TL和JFreeChart动态生成Word报告》本文介绍了使用POI-TL和JFreeChart生成包含动态数据和图表的Word报告的方法,并分享了实际开发中的踩坑经验,通过代码... 目录前言一、需求背景二、方案分析三、 POI-TL + JFreeChart 实现3.1 Maven

Java导出Excel动态表头的示例详解

《Java导出Excel动态表头的示例详解》这篇文章主要为大家详细介绍了Java导出Excel动态表头的相关知识,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解下... 目录前言一、效果展示二、代码实现1.固定头实体类2.动态头实现3.导出动态头前言本文只记录大致思路以及做法,代码不进

vue基于ElementUI动态设置表格高度的3种方法

《vue基于ElementUI动态设置表格高度的3种方法》ElementUI+vue动态设置表格高度的几种方法,抛砖引玉,还有其它方法动态设置表格高度,大家可以开动脑筋... 方法一、css + js的形式这个方法需要在表格外层设置一个div,原理是将表格的高度设置成外层div的高度,所以外层的div需要

SpringBoot实现动态插拔的AOP的完整案例

《SpringBoot实现动态插拔的AOP的完整案例》在现代软件开发中,面向切面编程(AOP)是一种非常重要的技术,能够有效实现日志记录、安全控制、性能监控等横切关注点的分离,在传统的AOP实现中,切... 目录引言一、AOP 概述1.1 什么是 AOP1.2 AOP 的典型应用场景1.3 为什么需要动态插

Java访问修饰符public、private、protected及默认访问权限详解

《Java访问修饰符public、private、protected及默认访问权限详解》:本文主要介绍Java访问修饰符public、private、protected及默认访问权限的相关资料,每... 目录前言1. public 访问修饰符特点:示例:适用场景:2. private 访问修饰符特点:示例:

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

Linux中chmod权限设置方式

《Linux中chmod权限设置方式》本文介绍了Linux系统中文件和目录权限的设置方法,包括chmod、chown和chgrp命令的使用,以及权限模式和符号模式的详细说明,通过这些命令,用户可以灵活... 目录设置基本权限命令:chmod1、权限介绍2、chmod命令常见用法和示例3、文件权限详解4、ch