Что вам нужно сделать, это создать @Bean
@Bean
public AccessDeniedHandler accessDeniedHandler(){
return new CustomAccessDeniedHandler();
}
, который у вас уже есть, и затем добавить этот обработчик в объект безопасности http, например так:
http.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(new Http403ForbiddenEntryPoint() {}) //remove this line or use Http401UnauthorizedEntryPoint instead
.and()
.authenticationProvider(getProvider())
.formLogin()
.loginPage("/login")
.successHandler(new AuthentificationLoginSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new AuthentificationLogoutSuccessHandler())
.invalidateHttpSession(true)
.and()
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/logout").permitAll()
.antMatchers("/api/categories").hasAuthority("USER")
.antMatchers("/api/createCategory").hasAuthority("ADMIN")
.anyRequest().permitAll()
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
Как вы может видеть, что вы пропали:
.and().exceptionHandling().accessDeniedHandler(accessDeniedHandler());
Дополнительно, удалите
@Autowired
private AccessDeniedHandler accessDeniedHandler;
, поскольку вы не должны автоматически связывать компонент, вы должны создать его с пользовательской реализацией.
РЕДАКТИРОВАТЬ : Если у вас есть @RestControllerAdvice
или @ControllerAdvice
в качестве глобального обработчика исключений, вы должны сделать следующее:
@ExceptionHandler(Exception.class)
public ResponseEntity<?> exception(Exception exception) throws Exception {
if (exception instanceof AccessDeniedException) {
throw exception;
}
...
, тогда это должно сработать, потому что, когда вы бросаете исключение, оно будет go для пользовательского обработчика, который мы делаем, что вы написали. Также вы можете отладить ExceptionTranslationFilter
метод handleSpringSecurityException
код из ExceptionTranslationFilter
private void handleSpringSecurityException(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, RuntimeException exception)
throws IOException, ServletException {
if (exception instanceof AuthenticationException) {
logger.debug(
"Authentication exception occurred; redirecting to authentication entry point",
exception);
sendStartAuthentication(request, response, chain,
(AuthenticationException) exception);
}
else if (exception instanceof AccessDeniedException) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authenticationTrustResolver.isAnonymous(authentication) || authenticationTrustResolver.isRememberMe(authentication)) {
logger.debug(
"Access is denied (user is " + (authenticationTrustResolver.isAnonymous(authentication) ? "anonymous" : "not fully authenticated") + "); redirecting to authentication entry point",
exception);
sendStartAuthentication(
request,
response,
chain,
new InsufficientAuthenticationException(
messages.getMessage(
"ExceptionTranslationFilter.insufficientAuthentication",
"Full authentication is required to access this resource")));
}
else {
logger.debug(
"Access is denied (user is not anonymous); delegating to AccessDeniedHandler",
exception);
accessDeniedHandler.handle(request, response,
(AccessDeniedException) exception);
}
}
}
, где вы можете увидеть, что accessDeniedHandler.handle(request, response,(AccessDeniedException) exception);
, в вашем случае CustomAccessDeniedHandler
, позвоните.
Я только что попробовал, и он работает нормально (у меня @ControllerAdvice
в качестве глобального обработчика исключений)
EDIT2: Вы должны удалить это line
.authenticationEntryPoint(new Http403ForbiddenEntryPoint() {})
from SecurityConfig
или измените его на Http401UnauthorizedEntryPoint
. Это проблема в вашем случае.