无法使用来自消息消费者的 Feign 客户端

Cannot use Feign client from a message consumer

我有一组使用 JHipster 创建并使用 Okta OAuth2 验证配置的三个微服务。

我还添加了与 RabbitMQ 消息服务的集成,因此其中一项服务在特定事件上生成消息,而另一项服务使用这些消息来更新其数据库。

现在,第二个服务要完全更新其数据,需要来自第三个服务的信息,我想用 FeignClient 调用它,但它因以下堆栈而失败:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:362)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:193)
at com.sun.proxy.$Proxy237.getAccessToken(Unknown Source)
at it.myefm.myspot.people.security.oauth2.AuthorizationHeaderUtil.getAuthorizationHeaderFromOAuth2Context(AuthorizationHeaderUtil.java:26)
at it.myefm.myspot.people.client.TokenRelayRequestInterceptor.apply(TokenRelayRequestInterceptor.java:23)
at feign.SynchronousMethodHandler.targetRequest(SynchronousMethodHandler.java:158)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:88)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)
at feign.hystrix.HystrixInvocationHandler.run(HystrixInvocationHandler.java:108)
at com.netflix.hystrix.HystrixCommand.call(HystrixCommand.java:302)
at com.netflix.hystrix.HystrixCommand.call(HystrixCommand.java:298)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
... 113 more

Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:42)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:350)
... 126 more

我认为问题在于 Feign 执行不是从 Web 请求开始的,因此上下文中没有身份验证信息...对吗?

是否有其他方式在服务之间访问我的数据?

问题是您的 TokenRelayRequestInterceptor 它试图从当前 thread-bound 安全上下文解析身份验证信息。

显然,当您处于消费者线程中时,您没有此类信息(至少默认情况下),因此解析失败。

您可以做的事情如下:

  • 在事件中传递必要的信息(如果它是访问令牌,则事件源系统可能会出现问题,因为它可能会过期)
  • 以某种方式尝试伪造第三个服务接受的访问令牌

在消费者端,您可以使用拦截器所需的信息手动设置 SecurityContext,或者您忘记消费者端的拦截器并手动提供第三个服务所需的数据(我想这只是一个Authorization header).

更新 您还可以在第三个服务中创建一个内部端点,它根本不需要任何身份验证,外部无法访问它。