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

相关文章

Java调用C#动态库的三种方法详解

《Java调用C#动态库的三种方法详解》在这个多语言编程的时代,Java和C#就像两位才华横溢的舞者,各自在不同的舞台上展现着独特的魅力,然而,当它们携手合作时,又会碰撞出怎样绚丽的火花呢?今天,我们... 目录方法1:C++/CLI搭建桥梁——Java ↔ C# 的“翻译官”步骤1:创建C#类库(.NET

如何搭建并配置HTTPD文件服务及访问权限控制

《如何搭建并配置HTTPD文件服务及访问权限控制》:本文主要介绍如何搭建并配置HTTPD文件服务及访问权限控制的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、安装HTTPD服务二、HTTPD服务目录结构三、配置修改四、服务启动五、基于用户访问权限控制六、

MyBatis编写嵌套子查询的动态SQL实践详解

《MyBatis编写嵌套子查询的动态SQL实践详解》在Java生态中,MyBatis作为一款优秀的ORM框架,广泛应用于数据库操作,本文将深入探讨如何在MyBatis中编写嵌套子查询的动态SQL,并结... 目录一、Myhttp://www.chinasem.cnBATis动态SQL的核心优势1. 灵活性与可

Mybatis嵌套子查询动态SQL编写实践

《Mybatis嵌套子查询动态SQL编写实践》:本文主要介绍Mybatis嵌套子查询动态SQL编写方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、实体类1、主类2、子类二、Mapper三、XML四、详解总结前言MyBATis的xml文件编写动态SQL

SpringBoot整合Sa-Token实现RBAC权限模型的过程解析

《SpringBoot整合Sa-Token实现RBAC权限模型的过程解析》:本文主要介绍SpringBoot整合Sa-Token实现RBAC权限模型的过程解析,本文给大家介绍的非常详细,对大家的学... 目录前言一、基础概念1.1 RBAC模型核心概念1.2 Sa-Token核心功能1.3 环境准备二、表结

SpringBoot实现Kafka动态反序列化的完整代码

《SpringBoot实现Kafka动态反序列化的完整代码》在分布式系统中,Kafka作为高吞吐量的消息队列,常常需要处理来自不同主题(Topic)的异构数据,不同的业务场景可能要求对同一消费者组内的... 目录引言一、问题背景1.1 动态反序列化的需求1.2 常见问题二、动态反序列化的核心方案2.1 ht

golang实现动态路由的项目实践

《golang实现动态路由的项目实践》本文主要介绍了golang实现动态路由项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习... 目录一、动态路由1.结构体(数据库的定义)2.预加载preload3.添加关联的方法一、动态路由1

Python Selenium动态渲染页面和抓取的使用指南

《PythonSelenium动态渲染页面和抓取的使用指南》在Web数据采集领域,动态渲染页面已成为现代网站的主流形式,本文将从技术原理,环境配置,核心功能系统讲解Selenium在Python动态... 目录一、Selenium技术架构解析二、环境搭建与基础配置1. 组件安装2. 驱动配置3. 基础操作模

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删