SecurityContextHolder.getContext () NPE при использовании @Async - PullRequest
2 голосов
/ 19 августа 2011

Я пытаюсь преобразовать последовательную последовательность вызовов службы Spring в асинхронную.

Я пометил метод с помощью @Async и добавил configExratutor taskExecutor.

Я вижу, что метод теперь вызывается асинхронно, но у меня возникают проблемы с SecurityContextHolder.getContext(), выдающим эту ошибку:

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

Был бы очень признателен за любые идеи. Спасибо!

Ответы [ 4 ]

6 голосов
/ 19 августа 2011

SecurityContext хранится в ThreadLocal . Так что, если вы обращаетесь к нему из нового потока, который нигде не был установлен, то SecurityContext будет нулевым.

Обновление : добавлена ​​локальная ссылка на Javadoc

3 голосов
/ 03 января 2012

Я нашел решение, изменив стратегию "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>
0 голосов
/ 15 мая 2017

Если вы хотите получить доступ к контексту безопасности в асинхронных вызовах, вы можете реализовать исполняющий контекст пул потоков с учетом контекста безопасности при создании потоков, как показано ниже.

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, переопределите другие методы в ThreadPoolTaskExecutor, который также поддерживает выполнение Runnable.

0 голосов
/ 14 марта 2016

Начиная с Spring-Security 3.2, есть хорошая аннотация @AuthenticationPrincipal, описанная в конце этого ответа.Это лучший способ, когда вы используете Spring-Security> = 3.2.Вы можете ввести его различными способами.Для получения дополнительной информации посмотрите на этот ответ

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...