您现在的位置是:首页 > 编程 > 

Spring Boot 集成 Spring Security(2)授权

2025-07-28 05:39:18
Spring Boot 集成 Spring Security(2)授权 Spring Boot 集成 Spring Security(2)授权 推荐框架 基于SpringBoot+Vue前后端分离的Java快速开发框架 项目简介:基于 JDK 17、Spring Boot 、Spring Security 6、JWT、Redis、Mybatis-Plus、Knife4j等构建后端,基

Spring Boot 集成 Spring Security(2)授权

Spring Boot 集成 Spring Security(2)授权

推荐框架 基于SpringBoot+Vue前后端分离的Java快速开发框架 项目简介:基于 JDK 17、Spring Boot 、Spring Security 6、JWT、Redis、Mybatis-Plus、Knife4j等构建后端,基于Vue 、Element-Plus 、TypeScript等构建前端的分离单体权限管理系统。 项目地址: 后端: gitee: .git gitcode: .git前端: gitee: .git .git 觉着有帮助,给个Star再走呗 搜“Harry技术”,关注我,带你看不一样的人间烟火!

在《Spring Boot 集成 Spring Security(1)》中,我们简单实现了 Spring Security 的认证功能,通过实现用户身份验证来确保系统的安全性。Spring Security的重要核心功能功能是“认证”和“授权”。接下来我们将深入了解授权机制,看如何控制用户在系统中可以访问的资源和操作。在 Spring Security 中,授权主要基于角和权限的概念进行控制。

角(Role):通常用来定义一组权限,用于定义用户身份的层级。比如 ADMI(ROOT) 角可能包含管理用户、查看日志等权限。

权限(Authority):具体的操作或资源访问权,则更细粒度地控制用户具体能做什么操作。比如 READ_PRIVILEGES、WRITE_PRIVILEGES 等。

Spring Security 提供了基于角和权限的访问控制机制,使我们可以轻松管理系统中的授权逻辑。

授权

要实现授权,我们需要在 Spring Security 的配置类中定义用户的角和访问策略。

代码实现过程:

  • 定义两个用户分别赋予角 admin -> ROOT、user -> USER
  • 定义Controller 使用不同的用户登录访问接口 AdminController、UserController、SecuredController
  • 登录不同账户验证授权

配置 SecurityFilterChain

代码语言:java复制
package cn.;

import org.annotation.Bean;
import org.annotation.Configuration;
import org.springframework.Customizer;
import org.springframework.EnableMethodSecurity;
import org.springframework.annotation.web.builders.HttpSecurity;
import org.springframework.annotation.EnableWebSecurity;
import org.springframework.userdetails.User;
import org.springframework.userdetails.UserDetails;
import org.springframework.userdetails.UserDetailsService;
import org.springframework.bcrypt.BCryptPasswordEncoder;
import org.springframework.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

/**
 * @author harry
 */
@Configuration
@EnableWebSecurity()
@EnableMethodSecurity(securedEnabled = true) // 开启方法级别的权限控制
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(auth -> auth
                        // 公开访问
                        .requestMatchers("/").permitAll()
                        // 只有 ROOT 角可以访问 /admin 目录下的资源
                        .requestMatchers("/admin/**").hasRole("ROOT")
                        // USER 和 ROOT 角都可以访问 /user 目录下的资源
                        .requestMatchers("/user/**").hasAnyRole("ROOT", "USER")
                        // 其他接口需认证
                        .anyRequest().authenticated()
                )

                // 开启基于表单的登录
                .formLogin(Customizer.withDefaults())
//                // 开启注销功能
//                .logout(Customizer.withDefaults())
//                // 开启 HTTP Basic 认证
//                .httpBasic(Customizer.withDefaults())
//                // 开启 CSRF 防护
//                .csrf(Customizer.withDefaults())
//                // 开启跨域资源共享
//                .cors(Customizer.withDefaults())
        ;

        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        // 创建用户
        UserDetails admin = User.builder()
                .username("admin")
                .password(("12456"))
                // 设置用户角为ROOT
                .roles("ROOT")
                .build();

        UserDetails user = User.builder()
                .username("user")
                .password(("12456"))
                // 设置用户角为USER
                .roles("USER")
                .build();

        // 将用户添加到内存中
        (admin);
        (user);
        return manager;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        // 使用 BCrypt 进行密码加密
        return new BCryptPasswordEncoder();
    }
}

代码说明

authorizeHttpRequests():用于定义 URL 路径的访问权限。

requestMatchers("/admin/**").hasRole("ROOT"):指定 /admin/** 下的所有路径都只有 ADMI 角的用户可以访问。

requestMatchers("/user/**").hasAnyRole("USER", "ROOT"):允许 USER 和 ROOT 角访问 /user/** 下的资源。

anyRequest().authenticated():表示系统中的其他请求都需要用户登录后才可以访问。

在 Spring Security 中,角是权限的一种特殊形式。实际上,hasRole() 是基于 hasAuthority() 实现的。当我们定义角时,Spring Security 会自动为角加上前缀**ROLE_**,所以 hasRole("ADMI") 实际上是hasAuthority("ROLE_ADMI")

基于注解的授权控制

除了在配置类中定义访问策略,Spring Security 还支持使用注解来控制方法的访问权限。常见的注解包括 @PreAuthorize@Secured

  • 使用 @PreAuthorize 注解 @PreAuthorize 注解可以用于方法级别的权限控制。它可以在方法执行之前检查用户的权限。
代码语言:java复制
@Slf4j
@RestController
public class AdminController {

    @GetMapping("/admin/info")
    @PreAuthorize("hasRole('ROOT')")  // 只有 ADMI 角才能访问
    public User adminInfo() {
        // 获取当前登录的用户信息
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        log.info("当前登录的用户信息:{}", ());
        return user;
    }
}
代码语言:java复制
@Slf4j
@RestController
public class UserController {

    @GetMapping("/user/info")
    public User getUserInfo() {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        log.info("当前登录的用户信息:{}", ());
        return user;
    }

    @GetMapping("/user/info2")
    @PreAuthorize("hasRole('USER')") // 只有 USER 角才能访问
    public User getUserInfo2() {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        log.info("当前登录的用户信息:{}", ());
        return user;
    }
}

使用 user 用户访问/admin/info时提示无权限,使用 admin 访问则正常打印用户信息。

  • 使用 @Secured 注解 @Secured 注解也可以实现类似的功能,限制方法访问的权限。

注意:使用 @Secured注解时,需要再 SecurityConfig 文件中添加@EnableMethodSecurity(securedEnabled = true) // 开启方法级别的权限控制,EnableMethodSecurity源码中看出@Secured默认时关闭状态。

创建一个SecuredController,写一个@Secured("ROLE_USER")才能访问的接口。

代码语言:java复制
@Slf4j
@RestController
public class SecuredController {

    /**
     * 使用 `@Secured`注解时,需要再 SecurityConfig 文件中添加
     	`@EnableMethodSecurity(securedEnabled = true) // 开启方法级别的权限控制`
     * 访问 /secured 需要有 ROLE_USER 权限
     */
    @GetMapping(value = "/secured")
    @Secured("ROLE_USER")
    public User hello() {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        log.info("当前登录的用户信息:{}", ());
        return user;
    }
}

自定义权限决策

在某些场景中,我们可能需要更加灵活的权限控制。在Spring Security中,@PreAuthorize、@PostAuthorize等注解支持SpEL表达式。如果要在表达式中调用其他对象的方法,需要在方法名前加上对象名。例如,@ss.hasPermission('monitor:operlog:list'),其中ss是Spring容器中的一个对象名,hasPermission则是该对象中的方法‌

  • 可以通过定义一个自定义的PermissionService类,并在其中实现权限验证逻辑。
代码语言:java复制
@Service("ss")
public class PermissionService {
    
    public Boolean hasPermission(String... permissi) {
        if (StringUtils.isEmpty(permissi)) {
            return false;
        }
        // 获取当前用户的所有权限
        List<String> perms = SecurityUtils.getUserDetails().getAuthorities().stream().map(GrantedAuthority::getAuthority).toList();
        // 判断当前用户的所有权限是否包含接口上定义的权限
        return (CommonCtant.ALL_PERMISSIO) || Arrays.stream(permissi).anyMatch(perms::contains);
    }

}

调用方法:

代码语言:java复制
 	@Operation(summary = "list 分页列表")
    @GetMapping(value = "/list")
    @PreAuthorize("@ss.hasPermission('monitor:operlog:list')")
    public R<IPage<SysOperationLog>> list(Page<SysOperationLog> page, SysOperationLog sysOperationLog) {
        return R.success(sysOperationLogService.page(page, Wrappers.lambdaQuery(sysOperationLog).orderByDesc(SysOperationLog::getCreateTime)));
    }

授权是确保系统安全的重要组成部分,它能帮助我们在系统中根据用户的身份和角对资源访问进行精细化控制。通过 Spring Security 提供的简单配置和注解支持,我们可以非常灵活地实现授权控制。

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1185672.html

相关标签:无
上传时间: 2025-07-22 10:48:41
留言与评论(共有 9 条评论)
本站网友 汽车销售排行榜
21分钟前 发表
授权主要基于角和权限的概念进行控制
本站网友 广东华南农业大学
7分钟前 发表
并在其中实现权限验证逻辑
本站网友 金银花的作用与功效
29分钟前 发表
@ss.hasPermission('monitor
本站网友 证券入门知识
19分钟前 发表
实际上
本站网友 玩游戏网
30分钟前 发表
如果要在表达式中调用其他对象的方法
本站网友 zhongtong
21分钟前 发表
在Spring Security中
本站网友 上海市酒店
26分钟前 发表
关注我
本站网友 微微新娘
19分钟前 发表
需要在方法名前加上对象名