2016-01-11 22 views
6

Celem jest dołączenie niektórych danych z kontekstu zabezpieczeń za pomocą RequestInterceptor, ale problem, że wywołanie SecurityContextHolder.getContext().getAuthentication() zawsze zwraca wartość null, nawet jeśli nie jest zerowa (jestem pewien 100%).Nieosiągalny kontekst zabezpieczeń za pomocą Feign RequestInterceptor

Rozumiem, że to dlatego, że Interceptor został stworzony i jest uruchamiany w innym wątku.

Jak mogę rozwiązać ten problem i uzyskać rzeczywiste dane z kontekstu zabezpieczeń?

Moje usługi:

@FeignClient(value = "api", configuration = { FeignConfig.class }) 
public interface DocumentService { 

    @RequestMapping(value = "/list", method = RequestMethod.GET) 
    DocumentListOperation list(); 
} 

My FeignConfig klasa:

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

Odpowiedz

3

udało mi się ustalić to, dzięki artykułu znalazłem here

Po pierwsze trzeba initiliaze HystrixRequestContext HystrixRequestContext.initializeContext(); .

Należy utworzyć własny kontekst, w którym będą przechowywane informacje, które należy przekazać do wątków potomnych Hystrix.

Oto przykład:

public class UserHystrixRequestContext { 

    private static final HystrixRequestVariableDefault<User> userContextVariable = new HystrixRequestVariableDefault<>(); 

    private UserHystrixRequestContext() {} 

    public static HystrixRequestVariableDefault<User> getInstance() { 
     return userContextVariable; 
    } 
} 

Musisz się zarejestrować nową strategię współbieżności, które zawinąć wywoływalnym sprzęgowi

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

Więc przed wywołaniem wywoływalnym obiektu możemy ustawić kontekst nowy wątek do kontekście rodzica.

Potem odbywa powinieneś być w stanie uzyskać dostęp do nowego kontekstu zdefiniowanego wewnątrz hystrix dziecku podaje

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

nadzieję, że pomoże ktoś.