Spring Security 6中Token过期时AuthenticationEntryPoint配置不生效问题
问题解决:自定义AuthenticationEntryPoint未触发及中文错误提示配置
问题原因
当使用Spring Security的oauth2ResourceServer(jwt())时,框架会为OAuth2相关的认证异常(如JWT过期、签名无效)默认使用BearerTokenAuthenticationEntryPoint,而非你配置的全局userAuthenticationEntryPoint,导致自定义逻辑未执行,同时返回默认英文错误头。
解决方案
1. 修改SecurityFilterChain配置
在oauth2ResourceServer块中显式指定自定义的AuthenticationEntryPoint,确保OAuth2认证异常走自定义逻辑:
@Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(new KeycloakRoleConverter(request)); return http .cors().and() .exceptionHandling() .authenticationEntryPoint(userAuthenticationEntryPoint) .and() .addFilterAfter(new UserIdentityContextFilter(contextHolder), BearerTokenAuthenticationFilter.class) .authorizeHttpRequests( authorize -> authorize .requestMatchers("/v1/corporate/{corporateId}/process-executor/**").access(corporateAuthManager) .requestMatchers("/v1/**").authenticated() .anyRequest().denyAll() ) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and().csrf().disable() .oauth2ResourceServer(oauth2 -> oauth2.jwt().jwtAuthenticationConverter(jwtAuthenticationConverter) .and() // 为OAuth2资源服务器指定自定义EntryPoint .authenticationEntryPoint(userAuthenticationEntryPoint) ) .build(); }
2. 优化自定义AuthenticationEntryPoint,返回中文提示
根据异常类型匹配对应的中文错误信息,覆盖默认英文提示:
import com.ba.cms.admin.dtos.ExceptionBean; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.MediaType; import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.jwt.JwtException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component; import java.io.IOException; import java.io.OutputStream; @Component public class UserAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { ExceptionBean bean; // 根据JWT异常类型返回对应中文提示 if (authException instanceof JwtException) { String errorMsg = authException.getMessage(); if (errorMsg.contains("expired")) { bean = new ExceptionBean(401, "未授权:令牌已过期"); } else if (errorMsg.contains("invalid signature")) { bean = new ExceptionBean(401, "未授权:令牌签名无效"); } else { bean = new ExceptionBean(401, "未授权:无效的令牌"); } } else { bean = new ExceptionBean(401, "未授权:请提供有效的认证信息"); } // 明确设置响应为JSON格式 response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); OutputStream outputStream = response.getOutputStream(); ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(outputStream, bean); outputStream.flush(); } }
内容的提问来源于stack exchange,提问作者Assaduzzaman Assad
相关产品推荐
相关产品推荐

