«1. Введение

В этой статье мы покажем, как настроить страницу отказа в доступе в проекте Spring Security.

Этого можно добиться либо с помощью конфигурации Spring Security, либо с помощью конфигурации веб-приложения в файле web.xml.

В оставшихся разделах мы более подробно рассмотрим каждую из этих опций.

2. Пользовательский JSP

Всякий раз, когда пользователь пытается получить доступ к странице, которая ограничена ролями, которых у него нет, приложение возвращает код состояния 403, что означает отказ в доступе.

Чтобы заменить страницу ответа о состоянии Spring 403 пользовательской, давайте сначала создадим файл JSP с именем accessDenied.jsp:

<body>
<h2>Sorry, you do not have permission to view this page.</h2>

Click <a href="<c:url value="/homepage.html" /> ">here</a>
to go back to the Homepage.
</body>

3. Конфигурация безопасности Spring

По умолчанию Spring Security имеет Определен ExceptionTranslationFilter, который обрабатывает исключения типа AuthenticationException и AccessDeniedException. Последнее выполняется с помощью свойства с именем accessDeniedHandler, которое использует класс AccessDeniedHandlerImpl.

Чтобы настроить это поведение для использования нашей собственной страницы, которую мы создали выше, нам нужно переопределить свойства класса ExceptionTranslationFilter. Это можно сделать с помощью конфигурации Java или конфигурации XML.

3.1. Доступ к странице запрещен

Используя Java, мы можем настроить процесс обработки ошибки 403, используя методы accessDeniedPage() или accessDeniedHandler() при настройке элемента HttpSecurity.

Давайте создадим конфигурацию аутентификации, которая ограничивает URL-адреса «/admin/**» ролью ADMIN и устанавливает страницу отказа в доступе на нашу пользовательскую страницу accessDenied.jsp:

@Override
protected void configure(final HttpSecurity http) throws Exception {
    http
      // ...
      .and()
      .exceptionHandling().accessDeniedPage("/accessDenied.jsp");
}

Давайте посмотрим в эквивалентной конфигурации XML для страницы отказа в доступе:

<http use-expressions="true">
    <access-denied-handler error-page="/accessDenied"/>
 </http>

3.2. Обработчик отказа в доступе

Использование обработчика отказа в доступе вместо страницы имеет то преимущество, что мы можем определить пользовательскую логику, которая будет выполняться перед перенаправлением на страницу 403. Для этого нам нужно создать класс, реализующий интерфейс AccessDeniedHandler и переопределяющий метод handle().

Давайте создадим собственный класс AccessDeniedHandler, который регистрирует предупреждающее сообщение для каждой попытки отказа в доступе, содержащее пользователя, предпринявшего попытку, и защищенный URL-адрес, к которому он пытался получить доступ:

public class CustomAccessDeniedHandler implements AccessDeniedHandler {

    public static final Logger LOG
      = Logger.getLogger(CustomAccessDeniedHandler.class);

    @Override
    public void handle(
      HttpServletRequest request,
      HttpServletResponse response, 
      AccessDeniedException exc) throws IOException, ServletException {
        
        Authentication auth 
          = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            LOG.warn("User: " + auth.getName() 
              + " attempted to access the protected URL: "
              + request.getRequestURI());
        }

        response.sendRedirect(request.getContextPath() + "/accessDenied");
    }
}

В конфигурации безопасности мы определить bean-компонент и установить пользовательский AccessDeniedHandler:

@Bean
public AccessDeniedHandler accessDeniedHandler(){
    return new CustomAccessDeniedHandler();
}

//...
.exceptionHandling().accessDeniedHandler(accessDeniedHandler());

Если мы хотим настроить класс CustomAccessDeniedHandler, определенный выше, с помощью XML, конфигурация будет выглядеть немного по-другому:

<bean name="customAccessDeniedHandler" 
  class="com.baeldung.security.CustomAccessDeniedHandler" />

<http use-expressions="true">
    <access-denied-handler ref="customAccessDeniedHandler"/>
</http>

4. Конфигурация приложения

Обработка Ошибка отказа в доступе может быть выполнена через файл web.xml веб-приложения путем определения тега страницы ошибки. Он содержит два вложенных тега, называемых кодом ошибки, которые определяют код состояния, который необходимо перехватить, и местоположение, которое означает URL-адрес, на который будет перенаправлен пользователь в случае обнаружения кода ошибки:

<error-page>
    <error-code>403</error-code>
    <location>/accessDenied</location>
</error-page>

Если приложение не имеют файла web.xml, как в случае с Spring Boot, аннотации Spring в настоящее время не предоставляют точной альтернативы тегу error-page. Согласно документации Spring, в этом случае рекомендуется использовать методы accessDeniedPage() и accessDeniedHandler(), представленные в разделе 3.

5. Заключение

В этой быстрой статье мы подробно описали различные способы что ошибка отказа в доступе может быть обработана с помощью пользовательской страницы 403.

Полный исходный код статьи можно найти в проекте GitHub.