旧版 (5.x 及更早)
传统的、全手动的方案。它适用于需要高度定制化 JWT 处理逻辑和错误响应格式的场景,或者是在遗留的 Spring Security 5.7 以下版本的项目中。
- 使用了一个自定义的 JwtAuthenticationFilter,并通过 addFilterBefore 将其插入到安全过滤器链中,放置在 UsernamePasswordAuthenticationFilter 之前。
工作流程:
- 请求到达 JwtAuthenticationFilter
- 该过滤器从请求头(如 Authorization: Bearer )中提取 JWT
- 过滤器自行验证 JWT 的签名、过期时间等(可能使用 JwtParser)
- 如果有效,则手动创建 Authentication 对象(通常是 UsernamePasswordAuthenticationToken)并存入 SecurityContextHolder
- 如果无效或没有令牌,则请求继续向下传递。由于后续过滤器无法认证,最终会由自定义的 AuthenticationEntryPoint 处理异常(返回 401 等)
异常处理:显式地设置了一个自定义的 authenticationEntryPoint。这意味着当用户未认证或 Token 无效时,你可以完全控制返回给客户端的 HTTP 响应体格式
java
@Configuration
@EnableWebSecurity
@RequiredArgsConstuctor
public class SecurityConfig extends WebSecurityConfigurerAdapter{
private final JwtAuthenticationFilter jwtAuthenticationFilter;//认证过滤器
private final AuthenticationEntryPoint authenticationEntryPoint;//认证入口点
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();//密码编码器
}
@Override
protected void configure(HttpSecurity http)throws Exception{
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/v1/user/register", "/api/v1/user/login").permitAll()
.antMatchers("/api/v1/user/**").authenticated()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
}
新版 (5.7+, 推荐用于 6.x)
现代的、基于标准的方案。它更简洁、更安全(受益于框架的内置安全特性),是新项目的首选。它将你从编写繁琐的 JWT 解析和验证代码中解放出来,让你更专注于业务逻辑。
- 使用了 .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt) 配置。这是 Spring Security 为 OAuth 2.0 Bearer Token 处理提供的开箱即用的功能
工作流程:
- 框架自动配置了一个 BearerTokenAuthenticationFilter
- 该过滤器从请求中提取 Bearer Token
- 它将 Token 传递给自动配置的 AuthenticationManager,该管理器会使用你定义的 JwtDecoder Bean 来解码和验证 JWT
- 如果有效,AuthenticationManager 会自动创建 JwtAuthenticationToken 并存入安全上下文
- 如果无效,资源服务器会自动处理异常,返回标准化的错误响应
异常处理:没有显式配置异常处理。OAuth2ResourceServer 会使用其默认的异常处理机制,返回类似 { "error": "invalid_token", "error_description": "..." } 这样的标准错误信息
java
@Configuration
@EnableWebSecurity //web安全
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
//特定路径公开,其他路径需要验证
.antMatchers("/auth/login", "/auth/token/refresh").permitAll()
.anyRequest().authenticated()
)
//简单的JWT配置
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
//明确配置为无状态
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
//明确禁用CSRF
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
//内置HMAC密钥解码器
@Bean
public JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withSecretKey(
Keys.hmacShaKeyFor("my-secret-key-which-must-be-at-least-32-characters-long".getBytes())
).build();
}
}
