Как исправить переопределение AccessDeniedHandler по умолчанию (AccessDeniedHandlerImpl) в конфигурации Spring Security (Java)?

#java #spring #spring-mvc #spring-security #access-denied

#java #spring #spring-mvc #spring-безопасность #доступ запрещен

Вопрос:

У меня есть небольшое веб-приложение, основанное на Spring MVC и Spring Security. У меня возникли трудности с настройкой собственного AccessDeniedHandler , который должен перенаправлять неавторизованных пользователей на мою пользовательскую страницу ошибок.

Я использую http.exceptionHandling().accessDeniedHandler(accessDeniedHandler) в своем классе конфигурации, который расширяется WebSecurityConfigurerAdapter . Значение по умолчанию AccessDeniedHandler продолжает вызываться, несмотря на настройку (я отлаживал ExceptionTranslationFilter ). В результате вместо моей пользовательской страницы ошибок отображается страница, определенная контейнером.

У вас есть идея, чего мне здесь не хватает? В чем может быть проблема? Большое спасибо за вашу помощь.

Выдержка из моего суперкласса WebSecurityConfigurerAdapter:

 @Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/static/**", "/login/*", "/login").permitAll()
                .antMatchers("/site/admin*").hasRole("ADMIN")
                .anyRequest().authenticated()
            .and().formLogin()
                .loginPage("/login")
                .usernameParameter("user-name")
                .passwordParameter("password")
                .defaultSuccessUrl("/site/welcome", true)
                .loginProcessingUrl("/process-login")
                .failureUrl("/login?login_error=1")
            .and().logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login")
            .and().sessionManagement()
                .invalidSessionUrl("/login")
            .and().csrf()
            .and().exceptionHandling().accessDeniedHandler(accessDeniedHandler);
}
 

Моя пользовательская реализация AccessDeniedHandler:

 @Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    private static Logger LOG = Logger.getLogger(CustomAccessDeniedHandler.class);

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
            AccessDeniedException accessDeniedException) throws IOException, ServletException {
        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            LOG.warn(String.format("User [%s] attempted to access the protected URL [%s]!", authentication.getName(), request.getRequestURI()));
        }

        response.sendRedirect(request.getContextPath()   "/site/403");
    }
}
 

Комментарии:

1. Попробуйте проверить, создан ли экземпляр CustomAccessDeniedHandler вообще. Может быть проблема с распознаванием компонента, например, компонента вне пути сканирования.

2. @StanislavL Вот и все! Я понятия не имею, почему он не вводит компонент в класс config. Другие классы в том же пакете вводятся без проблем. Я попытался назвать компонент и ввести его с помощью a @Qualifier , но безрезультатно… Я попытаюсь создать компонент вручную, используя @Bean аннотацию, но я не вижу причин, по которым он не работает так, как сейчас … 🙁

Ответ №1:

Я забыл назначить параметр autowired constructor для поля! Прошу прощения за публикацию здесь такой тривиальной проблемы, но после того, как я потратил полдня на поиски решения, я был слеп и пропустил его…

 public SpringSecurityConfiguration(
            AccessDeniedHandler accessDeniedHandler, ...) {
        this.accessDeniedHandler = accessDeniedHandler; // This line was missing.
        ...
}