Перейти к основному содержимому

Spring Security Custom AuthenticationFailureHandler

· 3 мин. чтения

1. Обзор

В этом кратком руководстве мы собираемся проиллюстрировать, как настроить `обработку ошибок аутентификации Spring Security в приложении Spring Boot. Цель состоит в том, чтобы аутентифицировать пользователей с помощью формы входа в систему .`

Для ознакомления с Spring Security и Form Login в Spring Boot обратитесь к этой и этой статье соответственно.

2. Аутентификация и авторизация

Аутентификация и авторизация часто используются вместе, поскольку они играют существенную и не менее важную роль, когда речь идет о предоставлении доступа к системе.

Однако они имеют разные значения и применяют разные ограничения при проверке запроса:

  • Аутентификация – предшествует Авторизации; речь идет о проверке полученных учетных данных; именно здесь мы проверяем, совпадают ли имя пользователя и пароль с теми, которые распознает наше приложение.
  • Авторизация это проверка наличия у успешно прошедшего проверку подлинности пользователя разрешений на доступ к определенным функциям приложения.

Мы можем настроить обработку ошибок аутентификации и авторизации , однако в этом приложении мы сосредоточимся на ошибках аутентификации.

3. Spring Security AuthenticationFailureHandler

Spring Security предоставляет компонент, который по умолчанию обрабатывает ошибки аутентификации.

Однако нередко мы оказываемся в ситуации, когда поведения по умолчанию недостаточно для удовлетворения требований.

Если это так, мы можем создать собственный компонент и обеспечить нужное поведение, реализуя интерфейс AuthenticationFailureHandler :

public class CustomAuthenticationFailureHandler 
implements AuthenticationFailureHandler {

private ObjectMapper objectMapper = new ObjectMapper();

@Override
public void onAuthenticationFailure(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception)
throws IOException, ServletException {

response.setStatus(HttpStatus.UNAUTHORIZED.value());
Map<String, Object> data = new HashMap<>();
data.put(
"timestamp",
Calendar.getInstance().getTime());
data.put(
"exception",
exception.getMessage());

response.getOutputStream()
.println(objectMapper.writeValueAsString(data));
}
}

По умолчанию Spring перенаправляет пользователя обратно на страницу входа с параметром запроса, содержащим информацию об ошибке.

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

Помимо компонента по умолчанию, в Spring есть другие готовые к использованию компоненты, которые мы можем использовать в зависимости от того, что мы хотим сделать:

  • DelegatingAuthenticationFailureHandler делегирует подклассы AuthenticationException разным AuthenticationFailureHandlers , что означает, что мы можем создать различное поведение для разных экземпляров AuthenticationException .
  • ExceptionMappingAuthenticationFailureHandler перенаправляет пользователя на определенный URL-адрес в зависимости от полного имени класса AuthenticationException.
  • ForwardAuthenticationFailureHandler перенаправит пользователя на указанный URL-адрес независимо от типа исключения AuthenticationException .
  • SimpleUrlAuthenticationFailureHandler — это компонент, который используется по умолчанию, он будет перенаправлять пользователя на failureUrl, если он указан; в противном случае он просто вернет ответ 401

Теперь, когда мы создали наш собственный AuthenticationFailureHandler , давайте настроим наше приложение и переопределим обработчик Spring по умолчанию:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication()
.withUser("user1").password(passwordEncoder.encode("user1Pass")).roles("USER");
}

@Override
protected void configure(HttpSecurity http)
throws Exception {
http
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.failureHandler(authenticationFailureHandler());
}

@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
return new CustomAuthenticationFailureHandler();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

Обратите внимание на вызов failureHandler() — здесь мы можем указать Spring использовать наш пользовательский компонент вместо компонента по умолчанию.

4. Вывод

В этом примере мы настроили обработчик ошибок аутентификации нашего приложения, используя интерфейс Spring AuthenticationFailureHandler .

Реализацию этого примера можно найти в проекте Github .

При локальном запуске вы можете получить доступ и протестировать приложение на локальном хосте: 8080.