OAuth2 身份验证的假装客户端不支持在异步方法中调用?



我正在开发一个带有feign and oauth2的弹簧云项目。为了获得更好的用户体验,这些操作已转移到异步方法(带有@ASYNC(中。但是出现了一个问题。我将OAuth2FeignRequestInterceptor添加为BEAN,并确保假定客户端可以在同步方法中正常工作(哪个线程在RequestContexTholder中具有正确的请求attributes(。

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

但是,如果我将这些操作移动到异步方法中,将会出现一个例外,因为没有requestContext,因此无法创建ScopedTarget.oauth2ClientContext。我已经搜索了stackoverflow.com并找到了一个解决方案:如何在ASYNC任务执行程序中启用请求范围使用RequestContextListener bean和这些代码,RequestContexTholder属于子线程将填充Parent thread的(请求线程(requestAttributes。由于异步方法将花费一段时间在调用假装客户端之前,因此将在调用假单客户端之前对请求进行重新遵循。响应请求时,请求contextListener将通过Invoke requestContexTholder.ResetRequestAttributes((;((requestContextListListener.java:76(重置RequestContexTholder中的请求Attributes,并在request request requestAttributes中进行请求。当它完成耗时的任务并尝试通过Feign Client发送某些内容时,Feign Client尝试从请求中获取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!

我不确定OAuth2FeignRequestCtector是否适合在异步方案中从RequestContext检索授权信息。

感谢您阅读我的问题并希望您的答复。

如果您使用的是弹簧,则可以将弹簧安全上下文绑定到子线程。

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

需要定义taskexecutor bean:

@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;
}
}

最后,最重要的是,当Servlet启动时,您需要启用SetThreadContextInherabristion:

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

相关内容

  • 没有找到相关文章

最新更新