php搭建网站教程,洛宁网站开发,山东济南发布最新通知,sns网站是什么文章目录 授权配置 SecurityFilterChain基于注解的授权控制自定义权限决策 在《Spring Boot 3 集成 Spring Security#xff08;1#xff09;》中#xff0c;我们简单实现了 Spring Security 的认证功能#xff0c;通过实现用户身份验证来确保系统的安全性。Spring Securit… 文章目录 授权配置 SecurityFilterChain基于注解的授权控制自定义权限决策 在《Spring Boot 3 集成 Spring Security1》中我们简单实现了 Spring Security 的认证功能通过实现用户身份验证来确保系统的安全性。Spring Security的重要核心功能功能是“认证”和“授权”。接下来我们将深入了解授权机制看如何控制用户在系统中可以访问的资源和操作。在 Spring Security 中授权主要基于角色和权限的概念进行控制。
角色Role通常用来定义一组权限用于定义用户身份的层级。比如 ADMINROOT 角色可能包含管理用户、查看日志等权限。 权限Authority具体的操作或资源访问权则更细粒度地控制用户具体能做什么操作。比如 READ_PRIVILEGES、WRITE_PRIVILEGES 等。
Spring Security 提供了基于角色和权限的访问控制机制使我们可以轻松管理系统中的授权逻辑。
授权
要实现授权我们需要在 Spring Security 的配置类中定义用户的角色和访问策略。
代码实现过程
定义两个用户分别赋予角色 admin - ROOT、user - USER定义Controller 使用不同的用户登录访问接口 AdminController、UserController、SecuredController登录不同账户验证授权
配置 SecurityFilterChain
package cn.harry.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;/*** author harry*/
Configuration
EnableWebSecurity()
EnableMethodSecurity(securedEnabled true) // 开启方法级别的权限控制
public class SecurityConfig {Beanpublic 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();}Beanpublic UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {InMemoryUserDetailsManager manager new InMemoryUserDetailsManager();// 创建用户UserDetails admin User.builder().username(admin).password(passwordEncoder.encode(123456))// 设置用户角色为ROOT.roles(ROOT).build();UserDetails user User.builder().username(user).password(passwordEncoder.encode(123456))// 设置用户角色为USER.roles(USER).build();// 将用户添加到内存中manager.createUser(admin);manager.createUser(user);return manager;}Beanpublic PasswordEncoder passwordEncoder() {// 使用 BCrypt 进行密码加密return new BCryptPasswordEncoder();}
}
代码说明 authorizeHttpRequests()用于定义 URL 路径的访问权限。 requestMatchers(/admin/**).hasRole(ROOT)指定 /admin/** 下的所有路径都只有 ADMIN 角色的用户可以访问。 requestMatchers(/user/**).hasAnyRole(USER, ROOT)允许 USER 和 ROOT 角色访问 /user/** 下的资源。 anyRequest().authenticated()表示系统中的其他请求都需要用户登录后才可以访问。 在 Spring Security 中角色是权限的一种特殊形式。实际上hasRole() 是基于 hasAuthority() 实现的。当我们定义角色时Spring Security 会自动为角色加上前缀 ROLE_所以 hasRole(ADMIN) 实际上是hasAuthority(ROLE_ADMIN)。 基于注解的授权控制
除了在配置类中定义访问策略Spring Security 还支持使用注解来控制方法的访问权限。常见的注解包括 PreAuthorize 和 Secured。
使用 PreAuthorize 注解 PreAuthorize 注解可以用于方法级别的权限控制。它可以在方法执行之前检查用户的权限。
Slf4j
RestController
public class AdminController {GetMapping(/admin/info)PreAuthorize(hasRole(ROOT)) // 只有 ADMIN 角色才能访问public User adminInfo() {// 获取当前登录的用户信息User user (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();log.info(当前登录的用户信息{}, user.toString());return user;}
}Slf4j
RestController
public class UserController {GetMapping(/user/info)public User getUserInfo() {User user (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();log.info(当前登录的用户信息{}, user.toString());return user;}GetMapping(/user/info2)PreAuthorize(hasRole(USER)) // 只有 USER 角色才能访问public User getUserInfo2() {User user (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();log.info(当前登录的用户信息{}, user.toString());return user;}
}使用 user 用户访问 /admin/info时提示无权限使用 admin 访问则正常打印用户信息。 使用 Secured 注解 Secured 注解也可以实现类似的功能限制方法访问的权限。 注意使用 Secured注解时需要再 SecurityConfig 文件中添加 EnableMethodSecurity(securedEnabled true) // 开启方法级别的权限控制,EnableMethodSecurity源码中看出Secured默认时关闭状态。 创建一个SecuredController,写一个Secured(ROLE_USER)才能访问的接口。
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(当前登录的用户信息{}, user.toString());return user;}
}自定义权限决策
在某些场景中我们可能需要更加灵活的权限控制。在Spring Security中PreAuthorize、PostAuthorize等注解支持SpEL表达式。如果要在表达式中调用其他对象的方法需要在方法名前加上对象名。例如ss.hasPermission(monitor:operlog:list)其中ss是Spring容器中的一个对象名hasPermission则是该对象中的方法
可以通过定义一个自定义的PermissionService类并在其中实现权限验证逻辑。 Service(ss)
public class PermissionService {public Boolean hasPermission(String... permissions) {if (StringUtils.isEmpty(permissions)) {return false;}// 获取当前用户的所有权限ListString perms SecurityUtils.getUserDetails().getAuthorities().stream().map(GrantedAuthority::getAuthority).toList();// 判断当前用户的所有权限是否包含接口上定义的权限return perms.contains(CommonConstant.ALL_PERMISSION) || Arrays.stream(permissions).anyMatch(perms::contains);}}调用方法 Operation(summary list 分页列表)GetMapping(value /list)PreAuthorize(ss.hasPermission(monitor:operlog:list))public RIPageSysOperationLog list(PageSysOperationLog page, SysOperationLog sysOperationLog) {return R.success(sysOperationLogService.page(page, Wrappers.lambdaQuery(sysOperationLog).orderByDesc(SysOperationLog::getCreateTime)));} 授权是确保系统安全的重要组成部分它能帮助我们在系统中根据用户的身份和角色对资源访问进行精细化控制。通过 Spring Security 提供的简单配置和注解支持我们可以非常灵活地实现授权控制。