微服务之间的访问令牌/授权

Posted

技术标签:

【中文标题】微服务之间的访问令牌/授权【英文标题】:Access Token/Authorization Between Microservices 【发布时间】:2018-01-15 12:45:01 【问题描述】:

我正在创建一个主要由移动应用程序使用的在线商店 REST API。该计划是使用 Spring Cloud 框架和 Spring Cloud OAuth 的微服务架构来确保安全性。

我的问题实际上是关于微服务之间通信的最佳实践:我应该让每个服务注册自己的令牌,还是应该只传递用户的令牌?

例如,我有 3 个服务:用户服务、帐户服务、订单服务。 我已经能够实现两个创建订单的过程:一个传递用户的令牌,另一个是每个服务都获得自己的令牌。我对这两种方法都使用了 Feign。

所以对于选项 1:order-service -> GET account-service/account/current

order-service 调用 account-service,它根据令牌中的 userId 返回帐户。然后 order-service 为该帐户创建一个订单。

或者对于选项 2:order-service -> GET account-service/account/user-id/userId

order-service 从发送的 token 中获取 userId,使用自己的 token 调用 account-service,然后使用检索到的帐户创建订单。

我真的不确定哪个选项最适合使用。一个更好地分离信息,但随后需要两个 Feign Client。然而,另一个不需要 2 个客户端,并且将某些端点阻止到外部客户端变得更容易,但是它需要创建额外的端点并且几乎每个服务都需要挖掘 Authentication 对象。

你的想法是什么?有没有人完全以一种或另一种方式实施他们的系统?或者我的想法完全错误。

感谢任何帮助。

【问题讨论】:

dev.to/s2agrahari/… 【参考方案1】:

当您进行服务器到服务器通信时,您实际上并不是代表用户行事,而是代表服务器本身行事。为此使用了客户端凭据。

以 curl 为例: curl acme:acmesecret@localhost:9999/oauth/token -d grant_type=client_credentials

您应该对您的 http 客户端执行相同的操作,您将获得访问令牌。用它来调用其他服务。

【讨论】:

【参考方案2】:

您应该使用使用client_credentials 流的客户端令牌进行服务间通信。这个流程默认暴露在 spring security oauth 的 /oauth/token 端点上。

除此之外,您还可以使用不暴露于互联网的私有 api,并且使用只能授予 oauth 客户端的角色进行保护。通过这种方式,您可以公开可能限制较少且验证较少的特权 API,因为您可以控制传递给它的数据。

在您的示例中,您可以公开一个公共端点 GET account-service/account/current(获取有关您自己的信息没有害处)和一个私有 api GET account-service/internal/account/user-id/userId 可以由 oauth 客户端专门用于查询任何现有用户。

【讨论】:

【参考方案3】:

我找到了以下 3 个选项:

如果每个微服务都在验证令牌,那么我们可以传递相同的令牌。但问题是——在同一令牌之间可能会过期。

如果我们使用 client_credentials 授权,那么我们有两个问题:一个是,我们需要在下一个微服务中发送用户名/ID。另一个是,我们需要请求两次——第一次是获取访问令牌,然后是实际调用。

如果我们只在 API 网关(不在微服务中)进行令牌验证,那么我们需要从 API 网关在每个微服务中发送用户名。并且需要更改微服务实现以接受该参数/标头。

【讨论】:

以上是关于微服务之间的访问令牌/授权的主要内容,如果未能解决你的问题,请参考以下文章

在微服务之间传递用户身份和授权

授权和微服务

如何将用户角色从授权服务器复制到下游微服务?

在微服务之间传播访问令牌

微服务内部调用不认证用户

在微服务架构的每个服务中验证访问令牌 (JWT)