Feign拦截器因为Hystrix的线程隔离获取不到正确的SecurityContext

我简单地实现了一个OAuth认证。已认证用户调用A服务,A服务又需要使用Feign调用B服务的时候,需要将access_token传递给B服务,我就是试着用Feign的拦截器,在请求头放入Authorization。但是在Feign+Hystrix情况下,通过SecurityContextHolder 获取 SecurityContext.getAuthentication(),Authentication 永远是 null.

我在网上看的,实现一个HystrixConcurrentStrategy,但是我实现完成之后,不知道如何注册进去,让它生效。
下面是我实现的具体情况:

@Component
public class SecurityContextHystrixStrategy extends HystrixConcurrencyStrategy {
    //在Feign拦截器中获取SecurityContext为null,原因时Hystrix使用线程隔离策略,先后线程不一样
    //通过重定义策略将SecurityContext传递给下一个线程。
    @Override
    public <T> Callable<T> wrapCallable(Callable<T> callable) {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        return new WrappedCallable<>(callable, securityContext);
    }

    static class WrappedCallable<T> implements Callable<T> {
        private final Callable<T> target;
        private final SecurityContext securityContext;

        public WrappedCallable(Callable<T> target, SecurityContext securityContext) {
            this.target = target;
            this.securityContext = securityContext;
        }
        @Override
        public T call() throws Exception {
            try {
                SecurityContextHolder.setContext(securityContext);
                return target.call();
            } finally {
                SecurityContextHolder.clearContext();
            }
        }
    }
}

问题:
请问我这样实现对不对?
还有我用@Component注解发现它并不会自动注册,那我该怎么注册进去,让他生效那?

尝试1

再次换信号量隔离又有了一个问题
我刚刚又试了试,是配置了

execution.isolation.strategy=SEMAPHORE   //最简单的配置了一个这个,其他额外配置没有

仍然获取不到SecurityContext,但是在Controller中是可以获取到额。
那是不是跟线程隔离策略也没多大关系?

@FeignClient(name = "leaner-user-service" , fallbackFactory = UserServiceFallbackFactory.class)
public interface UserServiceClient {
    @PostMapping("/findUserByUsername")
    Map<String,Object> findUserByUsername(@RequestParam("username") String username);
}

尝试2

彻底将Hystrix禁用,并将@FeignClient 中的 fallbackFactory 去掉,这时候可以正确获取到SecurityContext下的Authentication。

一定要帮我解惑,我挣扎一天了,这一天度日如年,自暴自弃,甚至都有点不想做程序了,太痛苦了。

阅读 6.1k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题