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)
我怎样才能让它正常工作?
根据对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 或更高版本,则支持开箱即用。否则需要一些实现,但这将是另一个问题。
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策略?
| 归档时间: |
|
| 查看次数: |
1926 次 |
| 最近记录: |