我正在尝试使用OAuth2设置FeignClient来实现“中继令牌”。我只希望FeignClient中继/传播来自ZuulProxy(已启用SSO)的OAuth2令牌。我使用Spring 1.3.1-RELEASE和Spring Cloud Brixton.M4。
我在自定义@FeignClient配置中添加了一个拦截器:
import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.client.OAuth2ClientContext; import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; import feign.RequestInterceptor; @Configuration public class FeignClientConfiguration { @Value("${security.oauth2.client.userAuthorizationUri}") private String authorizeUrl; @Value("${security.oauth2.client.accessTokenUri}") private String tokenUrl; @Value("${security.oauth2.client.client-id}") private String clientId; // See https://github.com/spring-cloud/spring-cloud-netflix/issues/675 @Bean public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2ClientContext oauth2ClientContext){ return new OAuth2FeignRequestInterceptor(oauth2ClientContext, resource()); } @Bean protected OAuth2ProtectedResourceDetails resource() { AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails(); resource.setAccessTokenUri(tokenUrl); resource.setUserAuthorizationUri(authorizeUrl); resource.setClientId(clientId); // TODO: Remove this harcode resource.setClientSecret("secret"); return resource; } }
然后像这样将配置添加到我的@FeignClient中:
@FeignClient(name = "car-service", configuration = FeignClientConfiguration.class) interface CarClient { @RequestMapping(value = "car-service/api/car", method = GET) ListgetAllCars(); }
该应用程序启动,但是当我从服务中使用Feign Client时,会得到:
2016-01-08 13:14:29.757 ERROR 3308 --- [nio-9081-exec-1] o.a.c.c.C.[.[.[. [dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [/user-service] threw exception [Request processing failed; nested exception is com.netflix.hystrix.exception.HystrixRuntimeException: getAllCars failed and no fallback available.] with root cause 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) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:41) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:340) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
我希望我的应用程序/微服务(使用@FeingClient调用另一个应用程序/微服务的应用)是无状态的。但是,我已经尝试了这两种方法,其中security.sessions = STATELESS(默认为SpringBoot)和security.sessions = ALWAYS(仅供尝试)。在这两种情况下,我都有相同的例外。
看一下代码,我发现OAuth2ClientContext被保存在Session中(Session作用域bean)。当您要实施启用了无状态OAuth2的应用程序/微服务时,它如何工作?准确地说,这是在当前情况下使用OAuth2的一大优势。但是,正如我所说,结果是相同的启用会话。
有人可以帮忙吗?
非常感谢!:-)
我发现问题在于Hystrix强制在另一个线程中执行代码,因此您无权访问请求/会话作用域的bean。我在启用Hystrix的情况下使用@FeignClient。当我使用feign.hystrix.enabled禁用Hystrix时:false从微服务A到微服务B的中继令牌(使用OAuth2FeignRequestInterceptor)的调用工作正常。
但是,希望能够使Hystrix保持启用状态。我在这篇文章中看到了一个在此方面改进Hystrix-Feign的新模块(feign-hystrix模块):
Spring Cloud Feign客户端调用是否在hystrix命令中执行?
但是,我看不到如何使用feign-hystrix正确完成设置,因此无法找到示例。请,您可以帮助解决这个问题还是使用feign-hystrix提供示例?
非常感谢!