如何建立Spring Security ContextHolder策略?
我在我的服务中使用异步方法(Spring3如何建立Spring Security ContextHolder策略?,spring,spring-security,Spring,Spring Security,我在我的服务中使用异步方法(Spring3@Asyncannotation)。我有一个问题-生成的线程没有安全上下文。原因是Spring安全默认使用SecurityContextHolder.MODE\u THREADLOCAL策略作为其上下文持有者。但是我需要使用SecurityContextHolder.MODE\u INHERITABLETHREADLOCAL策略。 目前,我在AuthenticationSuccessHandler中设置了策略。但在我看来,这不是一个好的做法 那么如何在上
@Async
annotation)。我有一个问题-生成的线程没有安全上下文。原因是Spring安全默认使用SecurityContextHolder.MODE\u THREADLOCAL
策略作为其上下文持有者。但是我需要使用SecurityContextHolder.MODE\u INHERITABLETHREADLOCAL
策略。
目前,我在AuthenticationSuccessHandler中设置了策略。但在我看来,这不是一个好的做法
那么如何在上下文配置文件中设置它呢?spring security的版本是3.0.0。您可以将环境变量
spring.security.strategy
设置为模式\u INHERITABLETHREADLOCAL
。您还可以有一个简单的bean,在web应用程序启动期间调用SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL)
并在上下文配置文件中初始化该值
如果@viator的答案对您有帮助,请查看java配置
@Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
methodInvokingFactoryBean.setTargetMethod("setStrategyName");
methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
return methodInvokingFactoryBean;
}
另一种解决方案,如@viator write:
<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" value="MODE_INHERITABLETHREADLOCAL" />
</bean>
像个魔术师一样工作。通过Java配置,无需反射
import javax.annotation.PostConstruct;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.context.SecurityContextHolder;
@Configuration
public class SecurityConfig {
@PostConstruct
public void enableAuthCtxOnSpawnedThreads() {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
}
谢谢你关于简单豆的建议。但我找到了更方便的解决方案-我在安全上下文中添加了以下代码:我仍然没有配置此bean的httpRequest.getRemoteUser()。请注意其中的含义:如果使用线程池,还应该使用setTaskDecorator()正如这里所解释的,我认为是非常重要的。@FrancoisMarot谢谢你的线程池提示!它救了我的命。使用
SecurityContextHolder.MODE\u INHERITABLETHREADLOCAL
,我的线程池有时无法获取用户上下文。使用executor.setTaskDecorator(runnable->new DelegatingSecurityContextRunnable(runnable))代码>,似乎总是这样。注意,对于web应用程序,这是一个错误的问题。使用模式\u INHERITABLETHREADLOCAL
可能会导致线程池中包含异步任务安全上下文错误的线程。更好的方法是使用一个执行器,在运行任务时委托安全上下文。请参见此处:后期注释:-)与配置类中的某种@PostConstruct相比,在安全性方面使用它是否有优势?我必须看一个示例。Postconstruct不会生成SpringBean,所以我不确定如何生成?我的意思是在@Postconstruct内部调用SecurityContextHolder.setStrategyName();这一切都是静态的,所以我猜它可能也会工作。我必须试一试。在这里的一篇文章中有一个完整的解释,不仅涉及@Async,还涉及任何自定义thread@hitch.united请看另一个答案: