为何无效/过期JWT时CustomAuthenticationEntryPoint的commence不执行?
问题原因分析与解决办法
问题诊断
核心原因是Spring Security的BearerTokenAuthenticationFilter在处理JWT令牌验证时,会自行捕获无效/过期令牌抛出的异常,并委托给默认的BearerTokenAuthenticationEntryPoint处理,不会将这些异常传递到你通过exceptionHandling()配置的全局AuthenticationEntryPoint。只有当请求中完全没有携带Bearer令牌时,才会触发全局配置的EntryPoint。
解决办法
以下两种方案可以解决这个问题,根据你的项目需求选择:
方案1:替换OAuth2资源服务器的默认EntryPoint
直接在oauth2ResourceServer配置中指定自定义的AuthenticationEntryPoint,覆盖默认的BearerTokenAuthenticationEntryPoint,这样所有JWT相关的认证异常(空令牌、无效、过期)都会走自定义实现。
示例代码:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .anyRequest().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2 .jwt(jwt -> jwt .decoder(jwtDecoder()) // 你的JWT解码器配置 ) // 替换默认的BearerTokenAuthenticationEntryPoint为自定义实现 .authenticationEntryPoint(new CustomAuthenticationEntryPoint()) ); return http.build(); }
方案2:全局异常捕获处理
通过@ControllerAdvice捕获JWT相关的认证异常,统一返回自定义响应。这种方式更灵活,适合需要集中处理多种异常的场景。
示例代码:
@ControllerAdvice public class GlobalAuthExceptionHandler { // 捕获所有JWT相关认证异常 @ExceptionHandler({ExpiredJwtException.class, InvalidJwtException.class, BadCredentialsException.class}) public ResponseEntity<Map<String, Object>> handleJwtAuthExceptions(Exception ex) { Map<String, Object> response = new HashMap<>(); response.put("code", HttpStatus.UNAUTHORIZED.value()); response.put("message", ex.getMessage()); return new ResponseEntity<>(response, HttpStatus.UNAUTHORIZED); } }
验证方式
配置完成后,分别测试三种场景:
- 无JWT令牌:确认
CustomAuthenticationEntryPoint.commence()被调用 - 无效JWT令牌:确认自定义逻辑触发(而非默认的BearerTokenEntryPoint)
- 过期JWT令牌:确认自定义逻辑触发
内容的提问来源于stack exchange,提问作者lilpipehit
相关产品推荐
相关产品推荐

