You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 20:58:27