Аутентифицированный симулированный клиент OAuth2 не поддерживается в асинхронном методе? - PullRequest
0 голосов
/ 02 июля 2019

Я занимаюсь разработкой весеннего облачного проекта с Feign и OAuth2.В этом проекте выполняются некоторые трудоемкие операции, и по завершении этих операций будут отправляться некоторые запросы.Чтобы улучшить взаимодействие с пользователем, эти операции были перемещены в асинхронный метод (с @Async).Но возникает проблема.Я добавил OAuth2FeignRequestInterceptor в качестве bean-компонента и убедился, что клиент Feign может правильно работать в синхронном методе (у какого потока есть корректные RequestAttributes в RequestContextHolder).

@Configuration
public class SomeConfiguration{
@Bean
    public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2ClientContext oAuth2ClientContext, BaseOAuth2ProtectedResourceDetails resource){
        return new OAuth2FeignRequestInterceptor(oAuth2ClientContext,resource);
    }
}

Но если я перенесу эти операции в асинхронный метод, возникнет исключение, что scopedTarget.oauth2ClientContext не может быть создан из-за отсутствия RequestContext.Я искал stackoverflow.com и нашел решение: Как включить область запроса в исполнителе асинхронной задачи С компонентом RequestContextListener и этим кодом RequestContextHolder, принадлежащий дочернему потоку, будет заполнен родительским потоком (поток запросов) RequestAttributes.Поскольку асинхронный метод будет стоить некоторого времени перед вызовом симулированного клиента, запрос будет отправлен до вызова симулированного клиента.Когда на запрос будет получен ответ, RequestContextListener сбросит RequestAttributes в RequestContextHolder путем вызова RequestContextHolder.resetRequestAttributes (); (RequestContextListener.java:76) и сделает запрос внутри RequestAttributes неактивным.Когда он завершил трудоемкие задачи и попытался отправить что-то с помощью симулированного клиента, симулированный клиент попытается получить oAuth2ClientContext из запроса и выдает исключение:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: Cannot ask for request attribute - request is not active anymore!

Я не уверен, что это такподходит для OAuth2FeignRequestInterceptor для получения информации об авторизации из RequestContext в асинхронном сценарии.

Спасибо, что прочитали мою проблему и надеетесь на ваш ответ.

1 Ответ

0 голосов
/ 19 июля 2019

Если вы используете Spring, вы можете связать контекст безопасности Spring с подпотоком.

SecurityContext context = SecurityContextHolder.getContext();
ExecutorService delegateExecutor = new ExecutorServiceAdapter(this.taskExecutor);
DelegatingSecurityContextExecutorService executor = new DelegatingSecurityContextExecutorService(delegateExecutor, context);
executor.invokeAll(tasks).stream()...

Необходимо определить bean-компонент taskExecutor:

@Configuration
public class ThreadConfig {
@Bean
public TaskExecutor threadPoolTaskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(4);
    executor.setMaxPoolSize(10);
    executor.setThreadNamePrefix("task_thread");
    executor.initialize();
    return executor;
}
}

Последнее, большинствоважно, чтобы при запуске сервлета вам нужно было включить setThreadContextInheritable:

DispatcherServlet dispatcherServlet = (DispatcherServlet)ctx.getBean("dispatcherServlet");
dispatcherServlet.setThreadContextInheritable(true);
...