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

Пользовательский Spring SecurityConfigurer

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

1. Обзор

Поддержка конфигурации Java Spring Security предоставляет нам мощные API-интерфейсы Fluent для определения сопоставлений и правил безопасности для приложения.

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

Для нашего быстрого примера здесь мы добавим функциональность, которая регистрирует ошибки для аутентифицированных пользователей в зависимости от заданного списка кодов состояния ошибки.

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

Чтобы начать определение нашего конфигуратора, сначала нам нужно расширить класс AbstractHttpConfigurer :

public class ClientErrorLoggingConfigurer 
extends AbstractHttpConfigurer<ClientErrorLoggingConfigurer, HttpSecurity> {

private List<HttpStatus> errorCodes;

// standard constructors

@Override
public void init(HttpSecurity http) throws Exception {
// initialization code
}

@Override
public void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(
new ClientErrorLoggingFilter(errorCodes),
FilterSecurityInterceptor.class);
}
}

Здесь основным методом, который нам нужно переопределить, является метод configure () , который содержит конфигурацию безопасности, к которой будет применяться этот конфигуратор.

В нашем примере мы зарегистрировали новый фильтр после последнего фильтра Spring Security. Кроме того, поскольку мы намерены регистрировать коды ошибок состояния ответа, мы добавили свойство списка errorCodes , которое можно использовать для управления кодами ошибок, которые мы будем регистрировать.

Мы также можем добавить дополнительную конфигурацию в метод init() , который выполняется перед методом configure() .

Далее давайте определим класс фильтра Spring Security, который мы регистрируем в нашей пользовательской реализации:

public class ClientErrorLoggingFilter extends GenericFilterBean {

private static final Logger logger = LogManager.getLogger(
ClientErrorLoggingFilter.class);
private List<HttpStatus> errorCodes;

// standard constructor

@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
//...

chain.doFilter(request, response);
}
}

Это стандартный класс фильтров Spring, который расширяет GenericFilterBean и переопределяет метод doFilter() . У него есть два свойства, представляющие регистратор, который мы будем использовать для отображения сообщений, и список кодов ошибок.

Рассмотрим подробнее метод doFilter() :

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null) {
chain.doFilter(request, response);
return;
}
int status = ((HttpServletResponse) response).getStatus();
if (status < 400 || status >= 500) {
chain.doFilter(request, response);
return;
}
if (errorCodes == null) {
logger.debug("User " + auth.getName() + " encountered error " + status);
} else {
if (errorCodes.stream().anyMatch(s -> s.value() == status)) {
logger.debug("User " + auth.getName() + " encountered error " + status);
}
}

Если код состояния представляет собой код состояния ошибки клиента, т. е. от 400 до 500, мы проверим список кодов ошибок .

Если это поле пусто, мы будем отображать любой код состояния ошибки клиента. В противном случае мы сначала проверим, является ли код ошибки частью данного списка кодов состояния.

3. Использование пользовательского конфигуратора

Теперь, когда у нас есть собственный API, мы можем добавить его в конфигурацию Spring Security, определив bean-компонент, а затем используя метод apply( ) HttpSecurity :

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
//...
.and()
.apply(clientErrorLogging());
}

@Bean
public ClientErrorLoggingConfigurer clientErrorLogging() {
return new ClientErrorLoggingConfigurer() ;
}
}

Мы также можем определить bean-компонент с определенным списком кодов ошибок, которые мы хотим регистрировать:

@Bean
public ClientErrorLoggingConfigurer clientErrorLogging() {
return new ClientErrorLoggingConfigurer(Arrays.asList(HttpStatus.NOT_FOUND)) ;
}

И это все! Теперь наша конфигурация безопасности будет включать настраиваемый фильтр и отображать сообщения журнала.

Если мы хотим, чтобы пользовательский конфигуратор был добавлен по умолчанию, мы можем использовать файл META-INF/spring.factories :

org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = com.foreach.dsl.ClientErrorLoggingConfigurer

И чтобы отключить его вручную, мы можем использовать метод disable() :

//...
.apply(clientErrorLogging()).disable();

4. Вывод

В этом кратком руководстве мы сосредоточились на расширенной функции поддержки конфигурации Spring Security — мы увидели, как определить наш собственный настраиваемый SecurityConfigurer .

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