Spring Security 实战
Web 应用的安全基石:认证(你是谁)和授权(你能做什么)。Spring Security 是 Java 生态最成熟的安全框架,本文讲清核心配置。
一、核心概念
认证(Authentication)验证用户身份,比如登录。授权(Authorization)验证用户权限,比如谁能访问管理后台。Spring Security 通过过滤器链(Filter Chain)处理每个请求。
| 概念 | 说明 |
|---|---|
| SecurityFilterChain | 安全过滤器链,拦截所有请求 |
| UserDetailsService | 加载用户信息 |
| PasswordEncoder | 密码加密验证 |
| JwtTokenProvider | JWT 生成与解析 |
二、依赖与基础配置
<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.5</version>
</dependency>
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
);
return http.build();
}
}
三、用户认证
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) {
User user = userRepository.findByUsername(username);
return org.springframework.security.core.userdetails.User
.withUsername(user.getUsername())
.password(user.getPassword())
.roles(user.getRole())
.build();
}
}
密码加密:永远不要明文存储密码。用 BCryptPasswordEncoder,它自带盐值,每次加密结果不同但可验证。
四、JWT 无状态登录
@Component
public class JwtTokenProvider {
@Value("${jwt.secret}")
private String secret;
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 86400000))
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
}
public String getUsername(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}
五、方法级权限控制
@RestController
@RequestMapping("/api/admin")
public class AdminController {
@PreAuthorize("hasRole('ADMIN')")
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Long id) {
userService.delete(id);
}
@PreAuthorize("hasAnyRole('ADMIN','EDITOR')")
@PutMapping("/posts/{id}")
public void updatePost(@PathVariable Long id, @RequestBody Post post) {
postService.update(id, post);
}
}
六、常见坑
第一,CSRF:前后端分离 + JWT 无状态时可以关掉 CSRF。第二,CORS:跨域请求要在 Security 配置里放行。第三,默认密码:Spring Boot 启动时会打印随机密码,生产环境必须换掉。
七、总结
Spring Security 的核心三步:配置 SecurityFilterChain 定义访问规则、实现 UserDetailsService 加载用户、用 JWT 做无状态认证。记住:安全是纵深防御,认证和授权只是第一道防线。