繁体   English   中英

如何使用Spring Cloud Security实现OAuth2“令牌交换”

[英]How to implement OAuth2 “Token Exchange” with Spring Cloud Security

我想知道是否有人举例说明如何使用Spring Cloud Security(使用OAuth2)实现“令牌交换”技术。

目前,我已经在微服务环境中使用ZuulProxy实现了“令牌中继”技术,以“中继”OAuth2令牌并实现SSO。 这很好,但暗示每个微服务使用相同的clientId(在ZuulProxy设置中指定为ZuulProxy仅使用authorization_code grant类型和clientId提供的中继)。 但是,对于微服务内部调用,我想“交换”令牌。 这意味着在某些情况下,ZuulProxy中继的令牌不是我需要用来验证/授权微服务A作为微服务B的客户端的令牌。

Spring Cloud参考文档目前说:“基于Spring Boot和Spring Security OAuth2,我们可以快速创建实现常见模式的系统,如单点登录,令牌中继和令牌交换 。” http://cloud.spring.io/spring-cloud-security/spring-cloud-security.html

我想在参考文档中使用“Token Exchange”它们意味着OAuth2的这个扩展的实现,在本规范中解释,这基本上是我需要的: https//tools.ietf.org/html/draft-ietf- OAuth的令牌交换-03

正如我所说,我了解如何使用SSO和令牌中继,但我无法在参考文档中看到有关如何实现“令牌交换”的进一步说明。 我也无法找到实现示例。

有谁知道我在哪里可以找到更多信息或示例?

非常感谢!

我很好奇为什么你需要“交换”令牌来进行从微服务A到微服务B的调用以及为什么中继还不够? 您通过交换令牌来处理服务间请求,您试图实现什么目标?

我们的设置非常类似于此北欧API条目中描述的内容。 简短版本是外部调用者使用不透明令牌,但是一旦请求通过我们的网关,每个微服务都会获得相同令牌的JWT表示。 我们必须实现一个自定义端点来执行对JWT交换的不透明。 当服务需要彼此交互时,我们不会在A需要调用B时交换令牌,我们只是中继令牌。 RestTemplate或Feign客户端将自动将令牌从A转发到B.因此,上下文不会丢失。

现在,如果我们想要控制访问,JWT可以指​​定一组受众值,或者我们可以通过范围强制访问。 我们实际上是根据用例进行两者的组合。

交换令牌并不是一种廉价的操作,实际上它的规模非常昂贵,应该真正考虑为什么需要进行令牌交换以进行服务内通信。 如果您的每个API请求都会导致服务A调用服务B并且您必须进行令牌交换,那么您将确保您的授权服务可以处理该类型的工作负载。 最后,IETF令牌交换仍处于草案状态,并且在其演变中已经发生了相当大的变化,因此在规范接近最终确定之前,我不会期望实施建议的方式。

我想这是你可能会尝试的。

在我的项目中,我们还使用OAuth2,Eureka,Ribbon进行微服务以相互通信。 为了将Ribbon与OAuth2一起使用,我们采用的方法略有不同。

首先,我们保持restTemplate不变。

  @LoadBalanced
  @Bean
  public RestTemplate restTemplate() {

但是,我们创建了FeignClientIntercepter实现RequestIntercepter,它在通过restTemplate发出请求时为OAuth设置授权令牌。

  @Component
  public class FeignClientInterceptor implements RequestInterceptor {

    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String BEARER_TOKEN_TYPE = "Jwt";

    @Override
    public void apply(RequestTemplate template) {
      SecurityContext securityContext = SecurityContextHolder.getContext();
      Authentication authentication = securityContext.getAuthentication();

      if (authentication != null && authentication
          .getDetails() instanceof OAuth2AuthenticationDetails) {
        OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication
          .getDetails();
        template.header(AUTHORIZATION_HEADER,
            String.format("%s %s", BEARER_TOKEN_TYPE, details.getTokenValue()));
      }
    }
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM