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

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

1. обзор

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

В этой быстрой статье мы увидим, как сделать еще один шаг вперед и фактически определить собственный конфигуратор; this is an advanced and flexible way to introduce custom logic into a standard security configuration.с

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

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

Чтобы начать определение нашего конфигуратора, сначалаwe need to extend the AbstractHttpConfigurer class:

public class ClientErrorLoggingConfigurer
  extends AbstractHttpConfigurer {

    private List 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);
    }
}

Здесьthe main method we need to override is the configure() method - содержит конфигурацию безопасности, к которой будет применяться этот конфигуратор.

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

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

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

public class ClientErrorLoggingFilter extends GenericFilterBean {

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

    // standard constructor

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

        chain.doFilter(request, response);
    }
}

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

Давайте подробнее рассмотрим метод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, мы проверим списокerrorCodes.

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

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

Теперь, когда у нас есть собственный API,we can add it to the Spring Security configuration by defining the bean, then by using the apply() method из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
public ClientErrorLoggingConfigurer clientErrorLogging() {
    return new ClientErrorLoggingConfigurer(Arrays.asList(HttpStatus.NOT_FOUND)) ;
}

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

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

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

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

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

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

В этом кратком руководстве мы сосредоточились на расширенной функции поддержки конфигурации Spring Security -we’ve seen how to define our own, custom SecurityConfigurer.

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