2011-08-19 219 views
2

我在嘗試將spring服務調用的一系列順序轉換爲異步。SecurityContextHolder.getContext()使用@Async時的NPE

我已經用@Async註釋了該方法,並添加了taskExecutor configuratinos。

我可以看到,該方法目前正在異步調用,但我有與SecurityContextHolder.getContext()引發此錯誤的問題:

java.util.concurrent.ExecutionException: java.lang.NullPointerException

會很感激任何見解。謝謝!

+0

請參閱http://stackoverflow.com/questions/3467918/how-to-set-up-spring-security-securitycontextholder-strategy – Ritesh

回答

6

SecurityContext存儲在ThreadLocal中。所以如果你從一個沒有設置它的新線程訪問它,那麼SecurityContext就是null。

更新:新增ThreadLocal的javadoc的鏈接

2

我找到了解決辦法,切換到 「MODE_INHERITABLETHREADLOCA」 解決了我的問題startegy。

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> 
<property name="targetClass" value="org.springframework.security.core.context.SecurityContextHolder"/> 
<property name="targetMethod" value="setStrategyName"/> 
<property name="arguments"> 
    <list> 
     <value>MODE_INHERITABLETHREADLOCAL</value> 
    </list> 
</property> 
</bean> 
0

由於彈簧安全3.2有這個答案的末尾描述的一個很好的註解@AuthenticationPrincipal。當你使用Spring-Security> = 3.2時,這是最好的方法。你可以用各種方式注入它。欲瞭解更多信息look at this answer

0

如果您想要訪問異步調用中的安全上下文,您可以實現上下文感知線程池執行器來存儲安全上下文時創建像下面的線程。

public class CustomExecutor extends ThreadPoolTaskExecutor { @Override public <T> Future<T> submit(Callable<T> task) { return super.submit(new ScopeAwareCallable<T>(task, SecurityContextHolder.getContext())); } }

public class ScopeAwareCallable<T> implements Callable<T> { 

private Callable<T> callableTask; 
private SecurityContext securityContext; 

public ScopeAwareCallable(Callable<T> task, SecurityContext secContex) { 
    this.callableTask = task; 
    this.securityContext = secContex; 
} 

@Override 
public T call() throws Exception { 
    if(securityContext != null){ 
     SecurityContextHolder.setContext(securityContext); 
    } 
    try { 
     return callableTask.call(); 
    } 
    finally { 
     SecurityContextHolder.clearContext(); 
    } 
} 

}

配置這是在Spring配置你的任務執行。如果您使用Runnable而不是Callable,則可以重寫支持Runnable執行的ThreadPoolTask​​Executor中的其他方法。