Я использую OAuth2RestTemplate в моем приложении загрузки Spring и работаю с каким-то ресурсом через него, поскольку он инкапсулирует всю информацию аутентификации, поэтому я могу просто отправлять запросы, не беспокоясь о токенах и других auth вещи.Использование OAuth2RestTemplate в многопоточном контексте
Это все работает нормально, пока я не отправлю запросы параллельно.
Из-за OAuth2RestTemplate имеет Session
объем (который является локальным, поскольку она содержит пользователь данные сеанса, связанные с), когда я пытаюсь использовать его в среде многопоточной, я получаю следующее исключение
org.springframework.beans.factory.BeanCreationException: Ошибка создания bean-компонента с именем 'scopedTarget.oauth2ClientContext': Scope 'session' неактивен для текущего потока; рассмотрите определение прокси-объекта с областью действия для этого компонента, если вы намерены ссылаться на него из одноэлементного; Вложенное исключение - это java.lang.IllegalStateException: запрос на привязку к потоку не найден: ссылаетесь ли вы на атрибуты запроса вне фактического веб-запроса или обрабатываете запрос за пределами исходного потока? Если вы действительно работаете в веб-запросе и все еще получите это сообщение, ваш код, вероятно, работает за пределами DispatcherServlet/DispatcherPortlet: В этом случае используйте RequestContextListener или RequestContextFilter, чтобы выставить текущий запрос .
Как я понимаю, это происходит потому, что эти отдельные потоки, где выполняется код, не связаны сеансом.
Единственное решение, которое я нашел сейчас, - привязка сеанса с новыми потоками вручную в коде, но мне это не нравится.
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
Stream.of(1, 2, 3).parallel().forEach(it -> {
RequestContextHolder.setRequestAttributes(requestAttributes);
//do something
RequestContextHolder.resetRequestAttributes();
});
RequestContextHolder.setRequestAttributes(requestAttributes);
Там в ticket on Spring Jira где обсуждались аналогичный вопрос, но до сих пор я все еще надеюсь, что есть какое-то решение связано с OAuth2RestTemplate.
Так что мне интересно, если кто-нибудь встретит это и как вы его разрешили.
вы сделали одноэлементный боб, чтобы он работал нормально, потому что Spring может обрабатывать одиночные силовые линии для разных потоков. Но проблема здесь в том, что oAuth2RestTemplate по умолчанию имеет область сеанса для хранения связанной с пользователем информации об аутентификации, поэтому каждый пользователь может использовать собственный компонент. Я не уверен, что это будет корректно работать с Singleton oAuth2RestTemplate. – ikryvorotenko
@ikryvorotenko Учитывая, что вы хотите использовать маркер доступа OAuth2 аутентифицированного принципала в «SecurityContext», вам фактически не нужен отдельный компонент для каждого пользователя. Вы можете обновить «OAuth2ClientContext» с помощью токена из «Аутентификация» в «SecurityContext». И я думаю, что бонусы с сессией не являются «настоящими» синглонами из-за магии прокси-сервера Spring в конце. На самом деле, мы успешно используем различные компоненты 'OAuth2RestTemplate' на основе подхода, описанного в моем ответе, а также дополнительные компоненты, которые используют статические учетные данные для имени пользователя и пароля для получения токена. –