Статьи

Spring Security и несколько цепочек фильтров

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

Конфигурация Spring Security

Давайте посмотрим на часть конфигурации для Spring Security, вы можете найти полный исходный код на Github . Я использую Spring Boot, но большинство частей должно быть одинаковым для всех приложений Spring.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .httpBasic()
                .and()
                .authorizeRequests().antMatchers("/secret/**").authenticated()
                .and()
                .authorizeRequests().antMatchers("/**").permitAll();
    }
}

В простейшем случае вы просто настраиваете HttpSecurity используя цепочку методов, которая является обычной в Spring Security. В этом случае мы включаем HTTP Basic Auth и требуем аутентификацию для одной конечной точки (все ниже /secure/ ). Все остальные запросы (обозначенные /** ) будут разрешены. Здесь используются шаблоны с синтаксисом пути Ant, но вы также можете использовать другой RequestMatcher чтобы решить, для каких частей вашего приложения требуется какая аутентификация.

Все функциональные возможности загрузки Spring реализованы в виде цепочки фильтров. Вызов функции httpBasic() выше фактически гарантирует, что соответствующий фильтр добавлен в цепочку фильтров. В этом случае BasicAuthenticationFilter проверит наличие заголовка Authorization и оценит его. Если он найден, он добавит объект Authentication в контекст и выполнит остальную часть цепочки фильтров. В конце цепочки находится FilterSecurityInterceptor который проверяет, требует ли запрашиваемый ресурс аутентификации и соответствует ли тот, который установлен, запрошенным ролям.

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

1
2
3
4
@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/resources/**");
}

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

Несколько цепочек фильтров

Иногда бывает необходимо использовать разные механизмы аутентификации для разных частей вашего приложения. Для этого Spring Security позволяет добавить несколько объектов конфигурации. Для этого является обычной практикой использование классов внутренней конфигурации, которые также могут совместно использовать некоторые части вмещающего приложения. Следующий класс добавляет две разные цепочки фильтров Spring Security.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class SecurityConfig {
    @Configuration
    public static class ApiConfiguration extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // doesn't really make sense to protect a REST API using form login but it is just for illustration
            http
                    .formLogin()
                    .and()
                    .authorizeRequests().antMatchers("/secret/**").authenticated()
                    .and()
                    .authorizeRequests().antMatchers("/**").permitAll();
        }
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/resources/**");
        }
    }
    @Order(1)
    @Configuration
    public static class ActuatorConfiguration extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .antMatcher("/management/**")
                    .httpBasic()
                    .and()
                    .authorizeRequests().antMatchers("/management/**").authenticated();
        }
        @Override
        public void configure(WebSecurity web) throws Exception {
            super.configure(web);
        }
    }
}

Оба класса наследуются от класса конфигурации адаптера и настраивают их HttpSecurity . Каждый из этих классов добавляет цепочку фильтров, и выполняется первый соответствующий ему класс. Аннотация @Order может использоваться, чтобы влиять на порядок цепочек фильтров, чтобы убедиться, что сначала выполняется правильная @Order .

Также может быть необходимо ограничить цепочку фильтров только определенной частью приложения, чтобы она не запускалась для других частей. ActuatorConfiguration ограничивается только сопоставлением запросов к /management/ . Помните, что в конфигурации есть два разных места, которые принимают RequestMatcher . Один в начале ограничивает URL, для которого запускается цепочка фильтров. Те, что после authorizeRequests() используются для определения того, какие запросы требуют какой тип аутентификации.

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

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

Ссылка: Spring Security и несколько цепочек фильтров от нашего партнера JCG Флориана Хопфа в блоге Dev Time .