Unreachable security context using the Use Request feature

The goal is to bind some data from the security context using RequestInterceptor, but the problem is that calling SecurityContextHolder.getContext().getAuthentication() always returns null, even if it is not null (I'm sure 100%) .

As I understand it, because the Interceptor is created and executed in another thread.

How can I solve this problem and get the actual data from the security context?

My service:

 @FeignClient(value = "api", configuration = { FeignConfig.class }) public interface DocumentService { @RequestMapping(value = "/list", method = RequestMethod.GET) DocumentListOperation list(); } 

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()); } } 
+6
source share
1 answer

I managed to figure it out thanks to the article I found here

First, you need to initialize HystrixRequestContext HystrixRequestContext.initializeContext(); .

You need to create your own Context in which you will store the information necessary for the transfer of Hystrix child streams.

Here is an example:

 public class UserHystrixRequestContext { private static final HystrixRequestVariableDefault<User> userContextVariable = new HystrixRequestVariableDefault<>(); private UserHystrixRequestContext() {} public static HystrixRequestVariableDefault<User> getInstance() { return userContextVariable; } } 

You need to register a new concurrency strategy that wraps the 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); } } } } 

Therefore, before calling the Callable object, we set the new context context to the parent.

After that, you will be able to access your new specific context inside the Hystrix child threads.

User = UserHystrixRequestContext.getInstance().get();

Hope this helps someone.

+3
source

All Articles