【问题标题】:Using @ControllerAdvice annotation @ExceptionHandler(Exception.class) is working but @ExceptionHandler({AuthenticationException.class) is not working使用 @ControllerAdvice 注释 @ExceptionHandler(Exception.class) 工作但 @ExceptionHandler({AuthenticationException.class) 不工作
【发布时间】:2021-03-24 17:05:40
【问题描述】:

我正在尝试使用 @ControllerAdvice 注释在 Spring Boot 中返回自定义 JSON 响应。下面是我的代码。 defaultExceptionHandler 如果应用程序中出现错误或 Spring Boot 服务抛出异常,则可以正常调用。但是即使我输入了错误的凭据,handleAuthenticationException 也不会被调用。在这种情况下,会返回默认的 spring-boot 响应。此服务是安全配置,设置为使用基本身份验证。

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class GlobalExceptionHandler {

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    @ExceptionHandler({AuthenticationException.class})
    public ServiceError handleAuthenticationException(final Exception ex) {
        //LOGGER.error(ex.toString(), ex);
        return new ServiceError(ServiceErrorCode.REQUEST_INVALID, ex.getMessage());
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public ServiceError defaultExceptionHandler(final Exception ex) {
        //LOGGER.error(ex.toString(), ex);
        return new ServiceError(ServiceErrorCode.SERVICE_ERROR, ex.getMessage());
    }
}

获取返回而不是自定义响应的默认响应:

   {
"timestamp": 16654436345,
"status": 401,
"error": "Unauthorized",
"message": "Bad credentials",
"path": "/mycontroller"}

安全配置类:

    @Configuration
public static class ServiceWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.
            csrf().
            disable().
            exceptionHandling().
        and().
            headers().
            frameOptions().
            disable().
        and().
            sessionManagement().
            sessionCreationPolicy(SessionCreationPolicy.STATELESS).
        and().
            authorizeRequests().
            antMatchers("/service/**").authenticated().
            antMatchers("/health").permitAll().
            antMatchers("/metrics").permitAll().
            antMatchers("/info").hasAuthority(AuthoritiesConstants.ADMIN).
            anyRequest().authenticated().and().httpBasic();
    }
}

【问题讨论】:

  • 根据您未显示的安全配置的设置方式,可能会在 MVC 调度发生之前触发 401。将您的日志记录转到DEBUG 并发布结果。
  • 感谢 chrylis 的建议。发布安全配置
  • 看来安全代码正在发回 HttpServletResponse.SC_UNAUTHORIZED 响应 - 给定 401。因此,永远不会抛出预期的异常。

标签: java spring-boot spring-mvc spring-security


【解决方案1】:

Spring MVC是基于servlet的,spring security是基于filter的,filter在servlet之前,所以你的controller中的异常处理不会被执行,因为filter已经失败了。

如果你想处理AuthenticationException,你需要处理它来实现AuthenticationEntryPoint并覆盖commence方法。

public void commence(HttpServletRequest request, HttpServletResponse response,
        AuthenticationException authException) throws IOException, ServletException

http.exceptionHandling().authenticationEntryPoint(myEntryPoint());

AuthenticationExceptionAccessDeniedException 已被 ExceptionTranslationFilter 处理。你只需要注入AuthenticationEntryPointAccessDeniedHandler(处理AccessDeniedException

【讨论】:

猜你喜欢
  • 2021-05-22
  • 1970-01-01
  • 1970-01-01
  • 2013-04-16
  • 2021-11-02
  • 2018-11-16
  • 1970-01-01
  • 2015-05-09
  • 1970-01-01
相关资源
最近更新 更多