Java Future - Spring Authentication在AuditorAware中为null

s1m*_*r3d 3 java spring spring-security mongodb completable-future

这是我的情景:

我的应用程序启用了Mongo审核,使用自定义AuditorAware从当前用户获取SecurityContext.这适用于同步方法,并且当前审计员已成功保存,但我无法使其与@Async方法一起正常工作.

我有一个异步方法(CompletableFuture),可以对我的Mongo数据库进行一些更新.当AuditorAware.getCurrentAuditor()被调用时,没有任何身份验证信息存在,我不能让现任核数师(SecurityContextHolder.getContext().getAuthentication()回报null).

@Override
public User getCurrentAuditor() {
   Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

   if (authentication == null || !authentication.isAuthenticated()
                || authentication instanceof AnonymousAuthenticationToken) {
            log.error("Not authenticated");
            return null;
    }

    [...]

}
Run Code Online (Sandbox Code Playgroud)

我用的是DelegatingSecurityContextAsyncTaskExecutor:

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(20);
        executor.setMaxPoolSize(100);
        executor.setQueueCapacity(200);
        executor.initialize();

        return new DelegatingSecurityContextAsyncTaskExecutor(executor);
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new ItacaExceptionHandler();
    }

} 
Run Code Online (Sandbox Code Playgroud)

我怎样才能让它正常工作?

Did*_*r L 6

根据对kuhajeyan 的回答的评论,您似乎没有正确使用CompletableFutureSpring @Async

如果您使用 eg 启动您的任务CompletableFuture.supplyAsync(Supplier),它们将由commonForkJoinPool而不是您配置的那个来执行@Async。您可以使用将 anExecutor作为参数的重载,但它实际上不会从@Async.

相反,您应该做的是让 Spring 处理任务执行,并简单地返回一个Completed , CompletableFuture如下所示:

@Async
public CompletableFuture<String> someMethod() {
    // do some computation, but return a completed future
    return CompletableFuture.completedFuture("Hello World!");
}
Run Code Online (Sandbox Code Playgroud)

然后,Spring 将在配置的执行器中异步执行您的方法,同时立即返回CompletableFuture将在您的方法返回时完成的a 。

如果您使用的是 Spring 4.2 或更高版本,则支持开箱即用。否则需要一些实现,但这将是另一个问题。


kuh*_*yan 5

Spring安全上下文始终绑定到Threadlocal.

也可以为安全上下文另外设置MODE_INHERITABLETHREADLOCAL.

@Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
    MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
    methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
    methodInvokingFactoryBean.setTargetMethod("setStrategyName");
    methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
    return methodInvokingFactoryBean;
}
Run Code Online (Sandbox Code Playgroud)

http://www.ogrigas.eu/spring/2010/04/inherit-spring-security-context-in-child-threads

如何设置Spring Security SecurityContextHolder策略?