Управление сессией с помощью Spring Security

Управляйте сеансом с помощью Spring Security

1. обзор

В этой статье мы покажем, какSpring Security allows us to control our HTTP Sessions.

Этот элемент управления варьируется от времени ожидания сеанса до разрешения одновременных сеансов и других расширенных настроек безопасности.

Дальнейшее чтение:

Получить информацию о пользователе в Spring Security

Как получить зарегистрированного в данный момент пользователя с помощью Spring Security.

Read more

Spring Security Запомнить меня

Пример Cookie Запомнить меня с Spring Security.

Read more

Spring Security Logout

Spring Logout Example - как настроить URL выхода из системы, logout-success-url и как использовать пользовательский компонент для обработки расширенных сценариев выхода из системы.

Read more

2. Когда создается сеанс?

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

  • always - сеанс всегда будет создан, если он еще не существует

  • ifRequired - сессия будет создана только при необходимости (default)

  • never - фреймворк никогда не создаст сам сеанс, но будет использовать его, если он уже существует

  • stateless - сеанс не будет создан или использован Spring Security

...

Конфигурация Java:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
}

Очень важно понимать, чтоthis configuration only controls what Spring Security does - не все приложение. Spring Security может не создать сеанс, если мы не дадим указание, но наше приложение может!

По умолчаниюSpring Security will create a session when it needs one - это «ifRequired».

Дляa more stateless application опция «never» гарантирует, что сама Spring Security не создаст никаких сеансов; однако, если приложение создаст его, Spring Security воспользуется им.

Наконец, самый строгий вариант создания сеанса - «stateless» - этоguarantee that the application will not create any session at all.

Это былоintroduced в Spring 3.1 и будет эффективно пропускать части цепочки фильтров Spring Security - в основном части, связанные с сеансом, такие какHttpSessionSecurityContextRepository,SessionManagementFilter,RequestCacheFilter.

Эти более строгие механизмы контроля прямо подразумевают, чтоcookies are not used и, следовательно,each and every request needs to be re-authenticated. Эта архитектура без сохранения состояния хорошо работает с API-интерфейсами REST и их ограничением без сохранения состояния. Они также хорошо работают с механизмами аутентификации, такими как базовая и дайджест-аутентификация.

3. Под капотом

Перед выполнением процесса аутентификации Spring Security запустит фильтр, отвечающий за сохранение контекста безопасности между запросами -SecurityContextPersistenceFilter. Контекст будет храниться в соответствии со стратегией - по умолчаниюHttpSessionSecurityContextRepository - которая использует сеанс HTTP в качестве хранилища.

Для атрибута strictcreate-session=”stateless” эта стратегия будет заменена другой -NullSecurityContextRepository - иno session will be created or used, чтобы сохранить контекст.

4. Управление одновременным сеансом

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

Первым шагом для включения одновременной поддержкиsession-control является добавление следующего слушателя вweb.xml:


    
      org.springframework.security.web.session.HttpSessionEventPublisher
    

Или определите его как Бин - следующим образом:

@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
    return new HttpSessionEventPublisher();
}

Это важно, чтобы убедиться, что реестр сеанса Spring Security -notified when the session is destroyed.

Чтобы включить сценарий, который разрешает несколько одновременных сеансов для одного и того же пользователя, в конфигурации XML следует использовать элемент<session-management>:


    
        
    

Или через конфигурацию Java:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement().maximumSessions(2)
}

5. Тайм-аут сеанса

5.1. Обработка тайм-аута сеанса

По истечении времени ожидания сеанса, если пользователь отправляет запрос сexpired session id, он будет перенаправлен на URL-адрес, настраиваемый через пространство имен:


    

Точно так же, если пользователь отправляет запрос с идентификатором сеанса, срок действия которого не истек, но полностьюinvalid, он также будет перенаправлен на настраиваемый URL:


    ...

Соответствующая конфигурация Java:

http.sessionManagement()
  .expiredUrl("/sessionExpired.html")
  .invalidSessionUrl("/invalidSession.html");

5.2. Настройте время ожидания сеанса с помощью Spring Boot

Мы можем легко настроить значение тайм-аута сеанса встроенного сервера, используя свойства:

server.servlet.session.timeout=15m

Если мы не укажем единицу продолжительности, Spring будет считать, что это секунды.

Короче говоря, с этой конфигурацией, после 15 минут бездействия сеанс истекает. Сеанс после этого периода времени считается недействительным.

Если мы сконфигурировали наш проект для использования Tomcat, мы должны помнить, что он поддерживает только точную минуту для времени ожидания сеанса, с минимальной минутой. Это означает, что если мы укажем значение тайм-аута, например,170s, это приведет к тайм-ауту в 2 минуты.

Наконец, важно отметить, что хотяSpring Session поддерживает аналогичное свойство для этой цели (spring.session.timeout), если оно не указано, автоконфигурация вернется к значению свойства, которое мы впервые упомянули.

6. Запретить использование параметров URL для отслеживания сеанса

Отображение информации о сеансе в URL-адресе растет вsecurity risk (с 7-го места в 2007 году до 2-го в 2013 году в списке 10 лучших приложений OWASP).

Starting with Spring 3.0, логика перезаписи URL-адреса, которая добавляла быjsessionid к URL-адресу, теперь может быть отключена путем установкиdisable-url-rewriting=”true” в пространстве имен<http>.

В качестве альтернативы, начиная с Servlet 3.0, механизм отслеживания сеанса также можно настроить вweb.xml:


     COOKIE

И программно:

servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));

Это выбирает, где хранитьJSESSIONID - в файле cookie или в параметре URL.

7. Защита от фиксации сеанса с помощью Spring Security

Инфраструктура предлагает защиту от типичных атак фиксации сеанса, настраивая то, что происходит с существующим сеансом, когда пользователь пытается снова аутентифицироваться:

 ...

Соответствующая конфигурация Java:

http.sessionManagement()
  .sessionFixation().migrateSession()

По умолчанию в Spring Security включена эта защита («migrateSession») - при аутентификации создается новый сеанс HTTP, старый становится недействительным, а атрибуты из старого сеанса копируются.

Если это не желаемое поведение, доступны два других варианта:

  • когда установлено «none», исходный сеанс не будет аннулирован

  • когда установлено «newSession», будет создан чистый сеанс без каких-либо атрибутов из старого сеанса, копируемого поверх

Далее мы обсудим, как защитить файл cookie сеанса.

We can use the httpOnly and secure flags to secure our session cookie:

  • httpOnly:, если true, скрипт браузера не сможет получить доступ к cookie

  • secure: если true, то cookie будет отправляться только через HTTPS-соединение

Мы можем установить эти флаги для нашего файла cookie сеанса вweb.xml:


    1
    
        true
        true
    

Эта опция конфигурации доступна начиная с Java сервлета 3. По умолчаниюhttp-only истинно, аsecure ложно.

Давайте также посмотрим на соответствующую конфигурацию Java:

public class MainWebAppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext sc) throws ServletException {
        // ...
        sc.getSessionCookieConfig().setHttpOnly(true);
        sc.getSessionCookieConfig().setSecure(true);
    }
}

If we’re using Spring Boot, we can set these flags in our application.properties:

server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=true

Наконец, мы также можем добиться этого вручную, используяFilter:

public class SessionFilter implements Filter {
    @Override
    public void doFilter(
      ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        Cookie[] allCookies = req.getCookies();
        if (allCookies != null) {
            Cookie session =
              Arrays.stream(allCookies).filter(x -> x.getName().equals("JSESSIONID"))
                    .findFirst().orElse(null);

            if (session != null) {
                session.setHttpOnly(true);
                session.setSecure(true);
                res.addCookie(session);
            }
        }
        chain.doFilter(req, res);
    }
}

9. Работа с сессией

9.1. Бобы с ограничением сеанса

Компонент может быть определен с областью действияsession, просто используя аннотацию @Scope для bean-компонентов, объявленных в веб-контексте:

@Component
@Scope("session")
public class Foo { .. }

Или с XML:

Затем бин можно просто ввести в другой боб:

@Autowired
private Foo theFoo;

А Spring свяжет новый компонент с жизненным циклом HTTP-сессии.

9.2. Внедрение необработанного сеанса в контроллер

Необработанный HTTP-сеанс также может быть введен непосредственно в методController:

@RequestMapping(..)
public void fooMethod(HttpSession session) {
    session.setAttribute(Constants.FOO, new Foo());
    //...
    Foo foo = (Foo) session.getAttribute(Constants.FOO);
}

9.3. Получение необработанного сеанса

Текущий HTTP-сеанс также можно получить программно черезraw Servlet API:

ServletRequestAttributes attr = (ServletRequestAttributes)
    RequestContextHolder.currentRequestAttributes();
HttpSession session= attr.getRequest().getSession(true); // true == allow create

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

В этой статье мы обсудили управление сессиями с помощью Spring Security. Кроме того, Spring Reference содержит очень хорошийFAQ on Session Management.

Как всегда, доступен код, представленный в этой статьеover on Github. Это проект, основанный на Maven, поэтому его легко импортировать и запускать как есть.