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 CallablecheckIfPrincipalPropagated() { 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 .