Перепутал маркер доступа в приложении Spring WebMVC с помощью Spring Security oAuthClient

#multithreading #spring-security #spring-webclient #spring-boot-starter-oauth2-client

#многопоточность #весна-безопасность #весна-веб-клиент #пружинный загрузчик-стартер-oauth2-клиент

Вопрос:

Я использую spring Spring Boot / Security 5.4.8 с OAuth2-клиентом.

В моем приложении есть фоновая обработка (пул потоков с 3 параллельными заданиями). Частью каждого задания является использование службы удаленного отдыха

  • для чего требуется Jwt-Аутентификация
  • в зависимости от контекста клиента задания необходима другая область (если задание обрабатывается для клиента A, область должна быть A и так далее…)

В тривиальном сценарии обрабатываются только задания одного клиента, и маркер доступа может быть использован повторно все время (до обновления). Это прекрасно работает.

Но с заданиями разных арендаторов маркер доступа должен быть изменен. К сожалению, токен доступа перепутался. Означает, что запрос задания 1 (Арендатор A) содержит запрос Арендатора B и так далее. Я не наблюдал никакого детерминированного поведения, когда работает сопоставление маркеров доступа и когда оно путается.

Мой полосатый код выглядит следующим образом.

У вас есть какие-либо предложения, как подойти к этой проблеме? Или я совершаю какие-то концептуальные ошибки?

 @Configuration public class CommonConfig {   @Bean  OAuth2AuthorizedClientManager defaultAuthClientManager(  ClientRegistrationRepository clientRegistrationRepository,  OAuth2AuthorizedClientService oAuth2AuthorizedClientService) {   OAuth2AuthorizedClientProvider authorizedClientProvider = new ClientCredentialsOAuth2AuthorizedClientProvider();  var authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager(  clientRegistrationRepository, oAuth2AuthorizedClientService);  authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);  authorizedClientManager.setAuthorizationSuccessHandler((authorizedClient, principal, attributes) -gt;  oAuth2AuthorizedClientService.saveAuthorizedClient(authorizedClient, principal));  authorizedClientManager.setAuthorizationFailureHandler(  new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(  (clientRegistrationId, principal, attributes) -gt;  oAuth2AuthorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName())));  return authorizedClientManager;  }   @Bean(name = "threadPoolTaskExecutor")  public TaskExecutor getAsyncExecutor() {  ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();  executor.initialize();  return executor;  }   @Bean  public ClientRegistrationRepository clientRegistrationRepository(OAuth2ClientProperties properties) {  final Listlt;ClientRegistrationgt; registrations = new ArrayListlt;gt;(OAuth2ClientPropertiesRegistrationAdapter.getClientRegistrations(properties).values());  final ClientRegistrationRepository parent = new InMemoryClientRegistrationRepository(registrations);   return (registrationId) -gt; {  final ClientRegistration clientRegistration = parent.findByRegistrationId("TEMPLATE");  if (clientRegistration == null) {  return null;  }   return ClientRegistration.withClientRegistration(clientRegistration)  .registrationId(registrationId)  .scope(resultingScopes)  .build();  }; }   @Component public class JobScheduler {    @Scheduled(cron = "0/10 * * * * *")  public void trigger() {  Listlt;Jobgt; jobs = this.mockService.getJobs();  jobs.forEach(job -gt; this.jobExecutor.process(job));  } }  @Component public class JobExecutor {   @Async("threadPoolTaskExecutor")  public CompletableFuturelt;JobStategt; processJob(Job job) {  try{  SecurityContextHolder.getContext().setAuthentication(job.getAuth());  this.myService.getMyRemoteServiceResponse(job.getId());  } finally {  SecurityContextHolder.getContext().setAuthentication(null);  }  }  }  @Service public class MyService {  public MyService(WebClient.Builder webClientBuilder) {  ...  }   private WebClient getWebClient(String scope) {  ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServletOAuth2AuthorizedClientExchangeFilterFunction(  authorizedClientManager);  oauth2Client.setDefaultClientRegistrationId(scope);   return webClientBuilder  .apply(oauth2Client.oauth2Configuration())  .build();  }   public String getMyRemoteServiceResponse(long id) {  String tenantName = SecurityContextHolder.getContext().getAuthentication().getName();  return this.getWebClient(tenantName)  .method(httpMethod)  .uri(uri)  .attributes(oauth2AuthorizedClient(this.getAuthorizedClient(this.getAuthenticationName())))  .retrieve()  .bodyToMono(String.class)  .block();  }  }