使用Feign客户端RequestInterceptor转发请求标头或安全上下文

时间:2015-12-03 10:01:48

标签: spring-boot spring-cloud netflix-feign

我想转发带有假装客户端RequestInterceptor的请求标头,但在RequestInterceptor.apply内,RequestContextHolder.getRequestAttributes()nullSecurityContextHolder.getContext().getAuthentication()也是hystrix.command.default.execution.isolation.strategy: SEMAPHORE (我最终也可以得到我的标题的价值。)

这在升级到Spring-Cloud Brixton之前已经工作了,其中hystrix命令现在必须可以在一个单独的线程中运行,因为更改为以下参数可以解决问题:

if (DBNull.Value.Equals(row["Effect_Date_From"])) 
{
   // null
}

现在,我不太热衷于更改此类默认值,如果没有必要,是否还有另一种推荐的转发标头方式?

由于

2 个答案:

答案 0 :(得分:4)

对于Spring Boot 2+ / Spring Cloud Finchley +,如果您只需要安全上下文,则可以设置以下属性:

hystrix.shareSecurityContext=true

请求拦截器应该可以工作。

对于其他用例或早期版本(非常感谢Spring Cloud Sleuth的灵感):

“所有”你要做的就是实现一个HystrixConcurrencyStrategy,每当有一个线程发生变化时都会传递信息。在侦探中做类似事情的类是here

对于我的具体案例,我会:

  1. Callable中的wrapCallable换行,例如,CallableWithAuthentication类,在构建时将保留当前的身份验证
  2. CallableWithAuthentication call方法首先会恢复以前保存的Authentication,然后调用原始操作,然后清理当前的Authentication,等等。
  3. 一旦HystrixConcurrencyStrategy启动,您的请求拦截器将再次起作用,即使使用线程隔离也是如此。

    注意检查项目的其余部分还有很多其他有趣的工具(例如RxJava)。

答案 1 :(得分:0)

只是为了详细说明@sebastian 的回答

public class RequestContextHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
    return new RequestAttributeAwareCallable<>(callable, RequestContextHolder.getRequestAttributes());
}

static class RequestAttributeAwareCallable<T> implements Callable<T> {

    private final Callable<T> delegate;
    private final RequestAttributes requestAttributes;

    public RequestAttributeAwareCallable(Callable<T> callable, RequestAttributes requestAttributes) {
        this.delegate = callable;
        this.requestAttributes = requestAttributes;
    }

    @Override
    public T call() throws Exception {
        try {
            RequestContextHolder.setRequestAttributes(requestAttributes);
            return delegate.call();
        } finally {
            RequestContextHolder.resetRequestAttributes();
        }
    }
}

}

然后在配置中的某个地方

@PostConstruct
public void init() {
    HystrixPlugins.getInstance().registerConcurrencyStrategy(new RequestContextHystrixConcurrencyStrategy());
}

参考 following post