【发布时间】:2016-04-13 03:51:45
【问题描述】:
我正在尝试使用 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)
List<CarVO> getAllCars();
}
应用程序启动,但是当我从我的服务中使用 Feign 客户端时,我得到:
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(会话范围 bean)中。当您想要实现启用 STATELESS OAuth2 的应用程序/微服务时,它是如何工作的?正是在我当前的场景中,这是使用 OAuth2 的一大优势。但是,正如我所说,结果是相同的启用会话。
有人可以帮忙吗?
非常感谢! :-)
【问题讨论】:
标签: spring spring-boot spring-cloud spring-security-oauth2