7

目標は、RequestInterceptor を使用してセキュリティ コンテキストからいくつかのデータをアタッチすることですが、SecurityContextHolder.getContext().getAuthentication()null ではないにもかかわらず、呼び出しが常に null を返すという問題があります (100% と確信しています)。

私が理解しているように、それはインターセプターが作成され、他のスレッドで実行されているためです。

この問題を解決して、セキュリティ コンテキストから実際のデータを取得するにはどうすればよいでしょうか?

私のサービス:

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

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

私の FeignConfig クラス:

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

1 に答える 1

5

ここで見つけた記事のおかげで、なんとかそれを理解することができました

まず、 HystrixRequestContext を初期化する必要がありますHystrixRequestContext.initializeContext();

Hystrix 子スレッドに渡す必要がある情報を格納する独自のコンテキストを作成する必要があります。

次に例を示します。

public class UserHystrixRequestContext {

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

    private UserHystrixRequestContext() {}

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

Callable インターフェイスをラップする新しい同時実行戦略を登録する必要があります

@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 オブジェクトを呼び出す前に、新しいスレッドのコンテキストを親のコンテキストに設定します。

それが完了すると、Hystrix 子スレッド内で新しく定義されたコンテキストにアクセスできるようになります。

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

それが誰かを助けることを願っています。

于 2016-01-15T13:13:37.997 に答える