Spring Boot未调用自定义handleAccessDeniedException()方法求助
问题根源分析
你遇到的核心问题是:错误凭证登录时抛出的是BadCredentialsException(属于AuthenticationException子类),而非AccessDeniedException。AccessDeniedException仅在「用户已成功认证,但没有权限访问目标资源」时才会触发,和「认证失败」是完全不同的场景,所以你的handleAccessDeniedException方法根本不会被调用。
解决方案
下面提供两种可行的解决方式,按需选择:
方式一:在全局异常处理器中添加认证失败异常处理
直接在GlobalExceptionHandler类中新增针对AuthenticationException的处理方法:
@ExceptionHandler(AuthenticationException.class) public ResponseEntity<ErrorDetails> handleAuthenticationException(AuthenticationException exception, WebRequest webRequest) { ErrorDetails errorDetails = new ErrorDetails(new Date(), "认证失败:" + exception.getMessage(), webRequest.getDescription(false)); return new ResponseEntity<>(errorDetails, HttpStatus.UNAUTHORIZED); }
注意:Spring Security的认证失败异常是在过滤器链阶段抛出的,默认不会被@ControllerAdvice捕获,因此这种方式可能需要配合方式二使用,或者直接用方式二更可靠。
方式二:自定义AuthenticationEntryPoint(推荐)
通过替换Spring Security默认的认证入口点,直接控制认证失败时的响应格式:
1. 创建自定义EntryPoint类
package com.springboot.blog.config; import com.springboot.blog.payload.ErrorDetails; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpStatus; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import java.io.IOException; import java.util.Date; public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { ErrorDetails errorDetails = new ErrorDetails(new Date(), "认证失败:无效的用户名或密码", request.getRequestURI()); response.setStatus(HttpStatus.UNAUTHORIZED.value()); response.setContentType("application/json"); new ObjectMapper().writeValue(response.getOutputStream(), errorDetails); } }
2. 在SecurityConfig中配置该EntryPoint
修改securityFilterChain方法,替换默认的httpBasic入口点:
@Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeHttpRequests((authorize) -> authorize.requestMatchers(HttpMethod.GET, "/api/**").permitAll() .anyRequest().authenticated() ) .httpBasic(httpBasic -> httpBasic.authenticationEntryPoint(new CustomAuthenticationEntryPoint()) ); return http.build(); }
配置完成后,当用户使用错误凭证登录时,会直接返回你定义的ErrorDetails格式响应,完全替代Spring的默认提示。
内容的提问来源于stack exchange,提问作者Answer
相关产品推荐
相关产品推荐

