使用 Feign 客户端 RequestInterceptor 转发请求标头或安全上下文
Posted
技术标签:
【中文标题】使用 Feign 客户端 RequestInterceptor 转发请求标头或安全上下文【英文标题】:Forward a request header or the security context with a Feign client RequestInterceptor 【发布时间】:2016-03-07 21:13:18 【问题描述】:我想转发一个带有假装客户端 RequestInterceptor 的请求标头,但是在 RequestInterceptor.apply
内,RequestContextHolder.getRequestAttributes()
是 null
,SecurityContextHolder.getContext().getAuthentication()
也是如此(我最终也可以获得我的标头的值)。
这在升级到 Spring-Cloud Brixton 之前可以正常工作,现在 hystrix 命令可能必须在单独的线程中运行,因为更改为以下参数可以解决问题:
hystrix.command.default.execution.isolation.strategy: SEMAPHORE
现在,如果没有必要,我不太热衷于更改这种默认值,现在是否有另一种推荐的转发标头的方式?
谢谢
【问题讨论】:
你可以将@RequestHeader
传递给一个feign方法。您还可以使用hystrix.command.<methodname>.execution.isolation.strategy: SEMAPHORE
单独将每个假装调用设置为 SEMAPHORE。
@spencergibb :谢谢,我就是这么想的。我将为我的项目的文档添加注释。
我认为我们希望以一种简单的方式配置线程与信号量的隔离。
@spencergibb :这可能会有所帮助......但根据 netflix 文档,建议使用 THREAD
隔离策略 (github.com/Netflix/Hystrix/wiki/…)。就我而言,我认为更改隔离级别以简化开发体验并不是一个好主意……我们将采用@RequestHeader
解决方案。非常感谢 Spring Cloud 的出色工作:-)
@SébastienNussbaumer 你有例子吗?我不太明白您如何访问拦截器中的 RequestHeader,即 apply 方法。我面临一个类似的问题,即线程本地变量由于第二个线程而返回 null。
【参考方案1】:
对于 Spring Boot 2+ / Spring Cloud Finchley +,如果您只需要安全上下文,您可以设置以下属性:
hystrix.shareSecurityContext=true
请求拦截器应该可以工作。
对于其他用例或早期版本(非常感谢Spring Cloud Sleuth 的启发):
“所有”你所要做的就是实现一个HystrixConcurrencyStrategy
,它在每次线程更改时传递信息。在 Sleuth 中做类似事情的类是here。
对于我的具体情况,我会:
-
将
Callable
包装在wrapCallable
中,例如使用CallableWithAuthentication
类,该类在构造时将保持当前身份验证
CallableWithAuthentication
call
方法将首先恢复之前保存的Authentication
,然后调用原始操作,然后清理当前的Authentication
,等等。
一旦您的HystrixConcurrencyStrategy
启动,您的请求拦截器将再次工作,即使使用线程隔离。
注意检查项目的其余部分,还有很多其他有趣的工具(例如 RxJava)。
【讨论】:
很高兴你喜欢!也许你会为我们贡献一些东西:D @MarcinGrzejszczak:时间是问题,但是嘿,为什么不呢:) 这仅在您从当前线程调用 feignclient 时有效。或者您是否有从另一个线程调用 feign 客户端的配置?我正在使用自定义线程池执行程序,它正在执行一些验证并调用外部服务。但在这种情况下,请求属性不会传播:( 当然@bilak,你必须用你的 ThreadPoolExecutor 做一些类似的事情......看看 spring cloud sleuth,可能有代码可以帮助你做到这一点...... 非常感谢!节省了很多时间)适用于版本云 - Greenwich.RELEASE 和启动 - 2.1.5.RELEASE【参考方案2】:只是为了详细说明@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
【讨论】:
以上是关于使用 Feign 客户端 RequestInterceptor 转发请求标头或安全上下文的主要内容,如果未能解决你的问题,请参考以下文章