Spring Security 6 + JWT 实战:从零构建无状态认证系统
Spring Security 6 JWT in Practice Building a Stateless Auth System from Scratch
| iDev Team | 2026-08-08T09:50:00
Spring Security 6 的 API 大幅变动,本文基于最新版本,手把手教你构建一套生产级的 JWT 无状态认证系统,包含 Token 刷新、权限控制、安全加固。
Spring Security 6 introduced major API changes. This hands-on guide walks you through building a production-grade JWT stateless authentication system with token refresh, access control, and security hardening.
为什么选 JWT? 在前后端分离架构中,传统的 Session 认证方式需要服务端存储会话状态,不利于水平扩展。JWT(JSON Web Token)实现了无状态认证,Token 自包含用户信息,服务端无需维护会话。 Spring Security 6 的变化 Spring Security 6(Spring Boot 3.x)相比旧版有几个重大变化: WebSecurityConfigurerAdapter 被废弃,改用 SecurityFilterChain Bean 方法安全注解默认使用 @PreAuthorize CSRF 配置简化 核心实现步骤 1. JWT 工具类 使用 JJWT 0.12.x 库(注意不要用旧版 0.9.x,API 完全不同): public String generateToken(String username) { return Jwts.builder() .subject(username) .issuedAt(new Date()) .expiration(new Date(System.currentTimeMillis() + expiration)) .signWith(getSigningKey()) .compact(); } 2. JWT 拦截器 继承 OncePerRequestFilter,从请求头提取 Token,验证后设置 SecurityContext。 3. Security 配置 @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .csrf(csrf -> csrf.disable()) .sessionManagement(s -> s.sessionCreationPolicy(STATELESS)) .authorizeHttpRequests(auth -> auth .requestMatchers("/api/auth/**").permitAll() .requestMatchers("/api/admin/**").authenticated() .anyRequest().permitAll()) .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class) .build(); } 安全加固 Token 过期时间不要太长,建议 24 小时 敏感操作添加二次验证 密码使用 BCrypt 加密,不要用 MD5 或 SHA JWT Secret 不要硬编码,走环境变量
Why JWT? In frontend-backend separated architectures, traditional session-based authentication requires server-side session storage, hindering horizontal scaling. JWT (JSON Web Token) enables stateless authentication — tokens contain user information, so the server doesn't need to maintain sessions. Changes in Spring Security 6 Spring Security 6 (Spring Boot 3.x) introduced several major changes: WebSecurityConfigurerAdapter is deprecated — use SecurityFilterChain beans instead Method security annotations now default to @PreAuthorize Simplified CSRF configuration Core Implementation Steps 1. JWT Utility Class Using JJWT 0.12.x (avoid the old 0.9.x — completely different API): public String generateToken(String username) { return Jwts.builder() .subject(username) .issuedAt(new Date()) .expiration(new Date(System.currentTimeMillis() + expiration)) .signWith(getSigningKey()) .compact(); } 2. JWT Interceptor Extend OncePerRequestFilter to extract the token from request headers, validate it, and set the SecurityContext. 3. Security Configuration @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .csrf(csrf -> csrf.disable()) .sessionManagement(s -> s.sessionCreationPolicy(STATELESS)) .authorizeHttpRequests(auth -> auth .requestMatchers("/api/auth/**").permitAll() .requestMatchers("/api/admin/**").authenticated() .anyRequest().permitAll()) .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class) .build(); } Security Hardening Keep token expiration reasonable — 24 hours recommended Add secondary verification for sensitive operations Use BCrypt for password hashing — never MD5 or SHA Never hardcode JWT secrets — use environment variables