使用Feign RequestInterceptor的无法访问的安全上下文 [英] Unreachable security context using Feign RequestInterceptor
问题描述
目标是使用RequestInterceptor从安全上下文附加一些数据,但问题是,调用SecurityContextHolder.getContext().getAuthentication()
始终返回null,即使它不为null(我确定是100%).
The goal is to attach some data from security context using RequestInterceptor, but the problem, that the calling SecurityContextHolder.getContext().getAuthentication()
always returns null even though it is not null (I am sure 100%).
据我了解,这是因为拦截器已创建并正在其他线程中运行.
As I understand that's because the Interceptor is created and is being run in other thread.
我该如何解决此问题并从安全上下文中获取实际数据?
How could I solve this problem and get actual data from security context?
我的服务:
@FeignClient(value = "api", configuration = { FeignConfig.class })
public interface DocumentService {
@RequestMapping(value = "/list", method = RequestMethod.GET)
DocumentListOperation list();
}
我的FeignConfig类:
My FeignConfig class:
@Bean
public RequestInterceptor requestInterceptor() {
return new HeaderInterceptor(userService);
}
public class HeaderInterceptor implements RequestInterceptor {
private UserService userService;
public HeaderInterceptor(UserService userService) {
this.userService = userService;
}
@Override
public void apply(RequestTemplate requestTemplate) {
Authentication a = SecurityContextHolder.getContext().getAuthentication()
requestTemplate.header("authentication", a.toString());
}
}
推荐答案
由于找到了首先,您需要初始化HystrixRequestContext HystrixRequestContext.initializeContext();
.
Firstly you need to initiliaze HystrixRequestContext HystrixRequestContext.initializeContext();
.
您必须创建自己的上下文,在其中存储需要传递给Hystrix子线程的信息.
You have to create your own Context in which you will store information you need to pass to Hystrix child threads.
以下是示例:
public class UserHystrixRequestContext {
private static final HystrixRequestVariableDefault<User> userContextVariable = new HystrixRequestVariableDefault<>();
private UserHystrixRequestContext() {}
public static HystrixRequestVariableDefault<User> getInstance() {
return userContextVariable;
}
}
您必须注册将包装Callable接口的新并发策略
You have to register new concurrency strategy that would wrap Callable interface
@Component
public class CustomHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
public CustomHystrixConcurrencyStrategy() {
HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
}
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
return new HystrixContextWrapper<T>(callable);
}
public static class HystrixContextWrapper<V> implements Callable<V> {
private HystrixRequestContext hystrixRequestContext;
private Callable<V> delegate;
public HystrixContextWrapper(Callable<V> delegate) {
this.hystrixRequestContext = HystrixRequestContext.getContextForCurrentThread();
this.delegate = delegate;
}
@Override
public V call() throws Exception {
HystrixRequestContext existingState = HystrixRequestContext.getContextForCurrentThread();
try {
HystrixRequestContext.setContextOnCurrentThread(this.hystrixRequestContext);
return this.delegate.call();
} finally {
HystrixRequestContext.setContextOnCurrentThread(existingState);
}
}
}
}
因此,在调用Callable对象之前,我们将新线程的Context设置为父级的上下文.
So before calling Callable object we set new thread's Context to parent's context.
完成此操作后,您应该能够在Hystrix子线程中访问新定义的上下文
After that is done you should be able to access your new defined context inside Hystrix child threads
User = UserHystrixRequestContext.getInstance().get();
希望对某人有帮助.
这篇关于使用Feign RequestInterceptor的无法访问的安全上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!