AccessDeniedHandler of Spring Security not Working While GlobalExceptionHandler existing

AccessDeniedHandler and AuthenticationEntryPoint does not work Because of the global exception handler

问题描述

在学习 Spring Security 的过程中,配置了权限异常处理器,但没有起作用,查找后发现是因为全局异常处理器已经处理了该异常,导致异常并没有传递到该处理器。

全局异常处理器

GlobalExceptionHandler.java
1
2
3
4
5
6
7
8
9
@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(Exception.class)
public ReturnVo unknownExceptionHandler(HttpServletRequest request, Exception e) {
e.printStackTrace();
return ReturnVo.error(CodeEnum.UNKNOWN_ERROR);
}
}

权限异常处理器

SecurityConfig.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
......

http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandler() {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
httpServletResponse.getWriter().write("{\"code\": \"402\", \"msg\": \"权限不足\"}");
}
});
}
}

解决方法

方法一:全局异常处理器中将该异常继续抛出

GlobalExceptionHandler.java
1
2
3
4
5
6
7
8
9
10
11
12
@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(Exception.class)
public ReturnVo unknownExceptionHandler(HttpServletRequest request, Exception e) throws Exception {
if (e instanceof AccessDeniedException){
throw e;
}
e.printStackTrace();
return ReturnVo.error(CodeEnum.UNKNOWN_ERROR);
}
}

方法二:将该异常处理器定义到全局异常处理器对应的类中

GlobalExceptionHandler.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(AccessDeniedException.class)
public void loginExceptionHandler(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
response.getWriter().write("{\"code\": \"402\", \"msg\": \"权限不足\"}");
}

@ExceptionHandler(Exception.class)
public ReturnVo unknownExceptionHandler(HttpServletRequest request, Exception e) {
e.printStackTrace();
return ReturnVo.error(CodeEnum.UNKNOWN_ERROR);
}
}