🌟Spring Security 权限配置详解:从基础到进阶
Spring Security 是一个功能强大、可高度自定义的安全框架,主要用于为基于 Spring 的应用程序提供身份验证和授权功能。
本篇文章将带你深入理解 Spring Security 的权限配置机制,掌握从用户认证到权限控制的核心配置方式。
一、Spring Security 的核心概念
在开始配置之前,先简单了解几个核心名词:
名词 | 说明 |
---|---|
Authentication | 认证,验证用户身份(用户名+密码) |
Authorization | 授权,判断当前用户是否有访问某资源的权限 |
SecurityContext | 安全上下文,保存当前用户的认证信息 |
UserDetailsService | 加载用户信息的接口 |
GrantedAuthority | 授权对象,表示用户拥有的权限 |
SecurityFilterChain | Spring Security 的过滤器链配置入口 |
二、Spring Security 权限配置方式概览
权限控制一般包含以下几种形式:
- 基于 URL 路径 的权限控制(最常用)
- 基于 方法注解 的权限控制(如
@PreAuthorize
) - 自定义 AccessDecisionManager 权限决策器
三、配置示例:Spring Boot + Spring Security 权限控制
1. 引入依赖
<!-- Spring Security 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2. 基础配置类
使用 SecurityFilterChain
代替旧版 WebSecurityConfigurerAdapter
:
@Configuration
@EnableMethodSecurity // 启用方法级权限控制
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/", "/login").permitAll()
.anyRequest().authenticated()
)
.formLogin(login -> login
.loginPage("/login")
.defaultSuccessUrl("/home")
.permitAll()
)
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login")
)
.csrf(csrf -> csrf.disable())
.build();
}
}
3. 自定义用户信息(UserDetailsService)
@Service
public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) {
// 模拟从数据库中查询
if ("admin".equals(username)) {
return User.withUsername("admin")
.password("{noop}admin123") // {noop}表示明文密码
.roles("ADMIN")
.build();
} else if ("user".equals(username)) {
return User.withUsername("user")
.password("{noop}user123")
.roles("USER")
.build();
}
throw new UsernameNotFoundException("用户不存在");
}
}
四、基于注解的权限控制(推荐)
Spring Security 支持通过注解方式对方法或类进行权限控制:
@RestController
@RequestMapping("/data")
public class DataController {
@GetMapping("/admin")
@PreAuthorize("hasRole('ADMIN')")
public String adminData() {
return "这是管理员数据";
}
@GetMapping("/user")
@PreAuthorize("hasAnyRole('USER','ADMIN')")
public String userData() {
return "这是用户数据";
}
}
常用注解说明
注解 | 说明 |
---|---|
@PreAuthorize | 方法执行前权限判断 |
@PostAuthorize | 方法执行后权限判断 |
@Secured("ROLE_ADMIN") | 只允许指定角色访问(默认需加 ROLE_ ) |
五、自定义权限判断表达式
假如你想用业务逻辑判断权限,可以这样:
@PreAuthorize("@authService.canAccess(#userId)")
public String getUserData(Long userId) {
return "业务数据";
}
在 AuthService
中定义权限逻辑:
@Component
public class AuthService {
public boolean canAccess(Long userId) {
// 获取当前登录用户的 ID
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String currentUsername = auth.getName();
// 自定义逻辑,比如根据用户名判断是否有权限查看这个 userId
return true;
}
}
六、权限控制最佳实践
- 权限与角色分离:不要把角色当权限用,系统更复杂时建议独立权限表。
- 接口权限控制+方法权限控制双保险。
- 菜单权限与接口权限绑定,提升用户体验。
- 使用数据库动态加载权限,支持多角色多权限灵活管理。
七、总结
Spring Security 提供了强大且灵活的权限控制机制,支持从 URL 到方法粒度的精细化配置。通过自定义 UserDetailsService
、SecurityFilterChain
和注解控制权限,我们可以轻松实现企业级权限管理。
✅ 核心关键词回顾:
SecurityFilterChain
UserDetailsService
@PreAuthorize
hasRole / hasAuthority
- 动态权限 + 自定义判断逻辑