Рубрики
Без рубрики

Поддержка асинхронности сервлета 3 с Spring MVC и Spring Security

Краткое введение в поддержку безопасности Spring для асинхронных запросов в Spring MVC.

Автор оригинала: baeldung.

1. введение

В этом кратком руководстве мы сосредоточимся на поддержке сервлета 3 для асинхронных запросов и на том, как Spring MVC и Spring Security обрабатывают эти .

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

И, конечно же, Spring Security интегрируется с @Async за пределами MVC и также обрабатывает HTTP-запросы.

2. Зависимости Maven

Чтобы использовать асинхронную интеграцию в Spring MVC, нам необходимо включить следующие зависимости в ваш pom.xml :


    org.springframework.security
    spring-security-web
    4.2.1.RELEASE


    org.springframework.security
    spring-security-config
    4.2.1.RELEASE

Последнюю версию зависимостей безопасности Spring можно найти здесь .

3. Spring MVC и @Async

Согласно официальному docs , Spring Security интегрируется с WebAsyncManager .

Первый шаг-убедиться, что наш springSecurityFilterChain настроен для обработки асинхронных запросов. Мы можем сделать это либо в Java config, добавив следующую строку в наш класс Servlet config:

dispatcher.setAsyncSupported(true);

или в конфигурации XML:


    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy
    true


    springSecurityFilterChain
    /*
    REQUEST
    ASYNC

Нам также необходимо включить параметр async-supported в нашей конфигурации сервлета:


    ...
    true
    ...

Теперь мы готовы отправлять асинхронные запросы с Контекстом безопасности , распространяемым вместе с ними.

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

4. Примеры использования

Давайте посмотрим на это в действии на простом примере:

@Override
public Callable checkIfPrincipalPropagated() {
    Object before 
      = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    log.info("Before new thread: " + before);

    return new Callable() {
        public Boolean call() throws Exception {
            Object after 
              = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            log.info("New thread: " + after);
            return before == after;
        }
    };
}

Мы хотим проверить, есть ли пружина Контекст безопасности распространяется на новый поток.

Метод, представленный выше, будет автоматически иметь свой Вызываемый , выполняемый с включенным Контекстом безопасности , как видно из журналов:

web - 2017-01-02 10:42:19,011 [http-nio-8081-exec-3] INFO
  o.baeldung.web.service.AsyncService - Before new thread:
  [email protected]:
  Username: temporary; Password: [PROTECTED]; Enabled: true;
  AccountNonExpired: true; credentialsNonExpired: true;
  AccountNonLocked: true; Granted Authorities: ROLE_ADMIN

web - 2017-01-02 10:42:19,020 [MvcAsync1] INFO
  o.baeldung.web.service.AsyncService - New thread:
  [email protected]:
  Username: temporary; Password: [PROTECTED]; Enabled: true;
  AccountNonExpired: true; credentialsNonExpired: true;
  AccountNonLocked: true; Granted Authorities: ROLE_ADMIN

Без настройки контекста безопасности для распространения второй запрос будет иметь значение null .

Существуют также другие важные варианты использования асинхронных запросов с распространяемым Контекстом безопасности :

  • мы хотим сделать несколько внешних запросов, которые могут выполняться параллельно и выполнение которых может занять значительное время
  • нам нужно выполнить некоторую значительную обработку локально, и наш внешний запрос может выполняться параллельно с этим
  • другие представляют собой сценарии “пожар и забудь”, например, отправка электронной почты

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

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

В этом коротком учебнике мы проиллюстрировали поддержку Spring для обработки асинхронных запросов в аутентифицированном контексте .

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

Этот пример также доступен в качестве проекта Maven на Github .