繁体   English   中英

使用 @ControllerAdvice 注释 @ExceptionHandler(Exception.class) 工作但 @ExceptionHandler({AuthenticationException.class) 不工作

[英]Using @ControllerAdvice annotation @ExceptionHandler(Exception.class) is working but @ExceptionHandler({AuthenticationException.class) is not working

我正在尝试使用@ControllerAdvice注释在 spring 引导中返回自定义 JSON 响应。 下面是我的代码。 如果应用程序中有错误或 spring 引导服务引发异常,则defaultExceptionHandler会被正常调用。 但是即使我输入了错误的凭据, 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"}

安全配置 class:

    @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();
    }
}

Spring MVC 基于 servlet,而 spring 安全性基于过滤器,过滤器在 servlet 之前,因此您的 controller 中的异常处理程序不会执行,因为它已经在过滤器中失败了。

如果要处理AuthenticationException ,则需要处理它以实现AuthenticationEntryPoint并覆盖commence方法。

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

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

AuthenticationExceptionAccessDeniedException已由ExceptionTranslationFilter处理。 您只需要注入AuthenticationEntryPointAccessDeniedHandler (处理AccessDeniedException

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM