Spring Security(5.x, 6.x ) RBAC访问控制

在 Spring Security 中,基于不同版本实现 RBAC(基于角色的访问控制)功能有一些不同的方式。RBAC 的基本原理是:定义用户、角色和权限的关系,并控制不同用户对资源的访问

Spring Security 不同版本的实现主要在配置方法、注解支持、以及代码风格上有所不同。以下是不同版本的 RBAC 配置方式和实现思路。

https://docs.spring.io/spring-security/reference/index.html

Spring Security 5.x 及以前的版本

在 Spring Security 5.x 版本中,RBAC 的实现一般是通过 WebSecurityConfigurerAdapter 类来配置 URL 访问规则、角色、权限等。方法级的权限控制 通过 @EnableGlobalMethodSecurity 注解开启。

1. 数据库表设计(通用)

RBAC 设计的数据库表包括 用户(User)角色(Role)权限(Permission)。基本表结构可以参考如下设计:

sql 复制代码
-- 用户表
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) UNIQUE NOT NULL,
    password VARCHAR(100) NOT NULL,
    enabled BOOLEAN DEFAULT TRUE
);

-- 角色表
CREATE TABLE roles (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    role_name VARCHAR(50) UNIQUE NOT NULL
);

-- 用户角色关联表(多对多)
CREATE TABLE user_roles (
    user_id BIGINT,
    role_id BIGINT,
    PRIMARY KEY (user_id, role_id),
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE
);

-- 权限表
CREATE TABLE permissions (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    permission_name VARCHAR(50) UNIQUE NOT NULL
);

-- 角色权限关联表(多对多)
CREATE TABLE role_permissions (
    role_id BIGINT,
    permission_id BIGINT,
    PRIMARY KEY (role_id, permission_id),
    FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE,
    FOREIGN KEY (permission_id) REFERENCES permissions(id) ON DELETE CASCADE
);
2. WebSecurityConfigurerAdapter 配置类

WebSecurityConfigurerAdapter 是 Spring Security 5 及以前版本的主要配置方式。以下是配置方法:

java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级别的权限控制
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final UserDetailsService userDetailsService;

    public SecurityConfig(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/admin/**").hasRole("ADMIN")  // 配置 URL 权限
                .antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated() // 其他请求都需要认证
                .and()
            .formLogin()
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
3. 方法级别权限控制

启用方法级别的安全注解后,可以在服务层或控制器层方法上直接使用 @PreAuthorize@Secured 注解来控制权限。

java 复制代码
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @PreAuthorize("hasRole('ADMIN')")
    public void adminMethod() {
        // 只有 ADMIN 角色的用户可以访问
    }

    @PreAuthorize("hasAnyRole('ADMIN', 'USER')")
    public void userOrAdminMethod() {
        // 只有 ADMIN 或 USER 角色的用户可以访问
    }
}

Spring Security 6.x 及以后的版本

Spring Security 6.x 中,WebSecurityConfigurerAdapter 已被弃用 ,推荐使用 SecurityFilterChain 配置和 @EnableMethodSecurity 注解。

1. SecurityFilterChain 配置类

不再继承 WebSecurityConfigurerAdapter,而是使用 SecurityFilterChain 来配置安全规则。同时,方法级别的权限控制启用方式从 @EnableGlobalMethodSecurity 改为 @EnableMethodSecurity

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity  // 启用方法级别的安全控制
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .permitAll()
                .and()
            .logout()
                .permitAll();

        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
2. 使用 @PreAuthorize@RolesAllowed 进行方法级别控制

在 Spring Security 6 中,@EnableMethodSecurity 启用后,仍可以使用 @PreAuthorize 等注解来实现方法级别的权限控制:

java 复制代码
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @PreAuthorize("hasRole('ADMIN')")
    public void adminMethod() {
        // 只有 ADMIN 角色的用户可以访问
    }

    @PreAuthorize("hasAnyRole('ADMIN', 'USER')")
    public void userOrAdminMethod() {
        // 只有 ADMIN 或 USER 角色的用户可以访问
    }
}
3. 配置基于角色的访问控制逻辑

基于角色的访问控制逻辑可以通过 SecurityFilterChain 中的 authorizeHttpRequests() 方法来配置,以匹配不同的 URL 路径。新的 requestMatchers() 方法替代了以前的 antMatchers() 方法,以更好地支持多种路径匹配。

小结

功能 Spring Security 5.x Spring Security 6.x
配置类 WebSecurityConfigurerAdapter SecurityFilterChain
方法级权限控制注解启用 @EnableGlobalMethodSecurity @EnableMethodSecurity
URL 匹配方法 antMatchers() requestMatchers()
密码加密方式 PasswordEncoder(如 BCrypt PasswordEncoder(如 BCrypt

总体来说,Spring Security 6.x 通过简化配置、弃用过时方法,使得 RBAC 的实现更加清晰简洁。

相关推荐
Yo_Becky15 分钟前
【PyTorch】PyTorch预训练模型缓存位置迁移,也可拓展应用于其他文件的迁移
人工智能·pytorch·经验分享·笔记·python·程序人生·其他
DIY机器人工房32 分钟前
0.96寸OLED显示屏 江协科技学习笔记(36个知识点)
笔记·科技·stm32·单片机·嵌入式硬件·学习·江协科技
future14122 小时前
每日问题总结
经验分享·笔记
循环过三天4 小时前
3-1 PID算法改进(积分部分)
笔记·stm32·单片机·学习·算法·pid
之歆4 小时前
Python-封装和解构-set及操作-字典及操作-解析式生成器-内建函数迭代器-学习笔记
笔记·python·学习
DKPT6 小时前
Java组合模式实现方式与测试方法
java·笔记·学习·设计模式·组合模式
受之以蒙6 小时前
Rust & WASM 之 wasm-bindgen 基础:让 Rust 与 JavaScript 无缝对话
前端·笔记·rust
茫忙然7 小时前
【WEB】Polar靶场 6-10题 详细笔记
笔记
eric*16887 小时前
尚硅谷张天禹老师课程配套笔记
前端·vue.js·笔记·vue·尚硅谷·张天禹·尚硅谷张天禹
Allen_LVyingbo8 小时前
数智读书笔记系列035《未来医疗:医疗4.0引领第四次医疗产业变革》
人工智能·经验分享·笔记·健康医疗