简体   繁体   English

使用 @Async 时的 SecurityContextHolder.getContext() NPE

[英]SecurityContextHolder.getContext() NPE when using @Async

I'm trying to convert a sequential series of calls of spring service to be asynchronous.我正在尝试将 Spring 服务的一系列顺序调用转换为异步。

I have annotated the method with @Async and added taskExecutor configuratinos.我已经用@Async注释了该方法并添加了 taskExecutor configuratinos。

I can see that the method is now being invoked asynchronously but I'm having issues with SecurityContextHolder.getContext() throwing this error:我可以看到该方法现在正在被异步调用,但我遇到了SecurityContextHolder.getContext()抛出此错误的问题:

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

Would really appreciate any insights.真的很感激任何见解。 Thanks!谢谢!

The SecurityContext is stored in a ThreadLocal . SecurityContext 存储在ThreadLocal 中 So if you access it from a new thread that didn't set it anywhere, then the SecurityContext is null.因此,如果您从未在任何地方设置它的新线程访问它,则 SecurityContext 为空。

Update : Added Threadlocal javadoc link更新:添加了 Threadlocal javadoc 链接

I found a solution, changing the startegy to "MODE_INHERITABLETHREADLOCA" solved my problem.我找到了一个解决方案,将 startegy 更改为“MODE_INHERITABLETHREADLOCA”解决了我的问题。

<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>

Since Spring-Security 3.2 there is a nice annotation @AuthenticationPrincipal described at the end of this answer.由于 Spring-Security 3.2 有一个很好的注释@AuthenticationPrincipal在这个答案的末尾描述。 This is the best way to go when you use Spring-Security >= 3.2.当您使用 Spring-Security >= 3.2 时,这是最好的方法。 You can inject it in various ways.您可以通过多种方式注入它。 For more information look at this answer有关更多信息,请查看此答案

If you want to access the security context in the asynchronous calls, You could implement the context aware thread pool executor to store the security context when creating threads like below.如果你想在异步调用中访问安全上下文,你可以实现上下文感知线程池执行器来在创建线程时存储安全上下文,如下所示。

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();
        }
    }
}

configure this as your task executor in the spring configuration.在 spring 配置中将此配置为您的任务执行器。 If you're using the Runnable instead of Callable, then override other methods in ThreadPoolTaskExecutor which supports the Runnable execution as well.如果您使用的是 Runnable 而不是 Callable,则覆盖也支持 Runnable 执行的 ThreadPoolTask​​Executor 中的其他方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SecurityContextHolder.getContext() 上的身份验证为空; - Authentication is null on the SecurityContextHolder.getContext(); SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - SecurityContextHolder.getContext().getAuthentication().getPrincipal(); SecurityContextHolder.getContext()。getAuthentication()返回String - SecurityContextHolder.getContext().getAuthentication() returns String 获取空或空的SecurityContextHolder.getContext()。getAuthentication() - Getting empty or null SecurityContextHolder.getContext().getAuthentication() Spring Security AuthenticationCredentialsNotFoundException,SecurityContextHolder.getContext为null - Spring Security AuthenticationCredentialsNotFoundException, SecurityContextHolder.getContext is null SecurityContextHolder.getContext().getAuthentication() 返回 null - SecurityContextHolder.getContext().getAuthentication() returning null Spring Security SecurityContextHolder.getContext()。getAuthentication()返回null - Spring Security SecurityContextHolder.getContext().getAuthentication() returns null SecurityContextHolder.getContext().getAuthentication().getCredentials() 认证后返回 null - SecurityContextHolder.getContext().getAuthentication().getCredentials() returns null after authentication 明确设置 SecurityContextHolder.getContext().setAuthentication(authenticationToken) 有什么需要? - What's the need of setting SecurityContextHolder.getContext().setAuthentication(authenticationToken) explicitly? 为什么 SecurityContextHolder.getContext().getAuthentication() 返回 null 值? - Why SecurityContextHolder.getContext().getAuthentication() returning null value?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM