spring-security: AccessDeniedHandler and AuthenticationEntryPoint does not work Because of the global exception handler

Summary

AccessDeniedHandler and AuthenticationEntryPoint do not work because the global exception handler is defined

Actual Behavior

When the request has an AuthenticationException or an AccessDeniedException, it does not enter my custom AccessDeniedHandler and AuthenticationEntryPoint.

1、Access to protected resources 2、Console prints AccessDeniedException,it does not enter my custom AccessDeniedHandler 3、I found it into my custom global exception handler.

Expected Behavior

enter my custom AccessDeniedHandler or AuthenticationEntryPoint

Configuration

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<?> exception(Exception exception) throws Exception {
        log.error(exception.getMessage(), exception);
        return ResponseEntity.ok("系统繁忙,请稍后再试!");
    }

}
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;
    private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    private StaticHeadersWriter staticHeadersWriter;

    {
        List<Header> headers = new ArrayList<>();
        headers.add(new Header("Access-Control-Allow-Origin", "*"));
        headers.add(new Header("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACES"));
        headers.add(new Header("Access-Control-Allow-Headers", Security.TOKEN));
        staticHeadersWriter = new StaticHeadersWriter(headers);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/swagger-ui.html",
                        "/swagger-resources/**",
                        "/webjars/**",
                        "/v2/api-docs")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .addFilterAt(new UsernamePasswordAuthenticationFilter(authenticationManager()), org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(new JwtAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class)
                .addFilterAfter(new OptionsRequestFilter(), HeaderWriterFilter.class)
                .exceptionHandling()
                .authenticationEntryPoint(new CustomizedAuthenticationEntryPoint())
                .accessDeniedHandler(new CustomizedAccessDeniedHandler())
                .and()
                .headers()
                .addHeaderWriter(staticHeadersWriter)
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .csrf()
                .disable()
                .logout()
                .disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .authenticationProvider(new JwtAuthenticationProvider())
                .userDetailsService(userService)
                .passwordEncoder(passwordEncoder)
        ;
    }

}

Version

spring-boot-starter-security 2.1.5.RELEASE

Sample

spring-security-demo

Additional

From the log printed by the console, I guess if the AccessDeniedException thrown by the MethodSecurityInterceptor when calling the beforeInvocation method is caught by the global exception handler, causing the superior ExceptionTranslationFilter to not catch the exception.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 18 (2 by maintainers)

Most upvoted comments

There really isn’t anything we can do on our side. It might be that users actually want to catch the exception and process it. Instead we recommend that if you get a Security related exception to re-throw it.

Similar questions. Neither call AuthenticationEntryPoint, nor call global exception handler. But get: { “timestamp”: 1589452582946, “status”: 500, “error”: “Internal Server Error”, “message”: “invalid token”, “path”: “/auth/xxx” }

@aboutZZ 我之前写的spring-security-demo,定义了一个全局异常捕获器捕获spring-security相关的异常,然后继续向上抛出就能进入到AccessDeniedHandler和AuthenticationEntryPoint中了,我怀疑你没有将这两个类配置进去,你看一下这个配置类WebSecurityConfig中的configure方法

@zhuzhiyun Catch AccessDeniedException and AuthenticationException and throw them, AccessDeniedHandler and AuthenticationEntryPoint will work normally.see GlobalExceptionHandler

Thank you for your reply, my current practice is to re-throw spring-security related exceptions.