#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.
...
}