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

Posted

技术标签:

【中文标题】在微服务之间传递用户身份和授权【英文标题】:Passing user identity and authorization between microservices 【发布时间】:2019-07-09 19:07:29 【问题描述】:

我很困惑 - 以异步方式在微服务之间传递用户身份(授权信息)的最佳方式是什么?

假设我已经有了处理身份验证和发布 JWT 令牌的入口点(api 网关)。然后用户使用这个令牌调用一些 API 端点。至此,一切都清楚了。现在 - 这个端点需要与另一个微服务通信。该微服务必须获得授权信息(角色等)。 另外 - 这个通道是异步的(JMS/Kafka),这意味着处理可能会延迟......

我也在考虑其他情况:我们有两个服务 A 和 B。它们都公开了可能被外部用户访问的 API(JWT 令牌身份验证),但它们还需要异步协作(通过 JMS)。他们都需要用户身份上下文。再说一遍——如何通过?

我可以:

    将 JWT 令牌与队列消息一起传递 - 安全吗?如果令牌在目标服务开始处理之前过期怎么办? 从 JWT 令牌转换信息并将其作为 HTTP 标头传递 - 如果目标服务返回信息怎么办 - 我需要从该响应中重新获得授权上下文(它仍然必须在特定用户的上下文中处理),但这让我处理两个授权类型:JWT 和从异步进程返回的... ...?

他们对我都有缺点,我找不到通用的解决方案......

--编辑

考虑案例:有产品目录服务和订购服务。两者都公开了公共 API。用户下订单,等待处理。第一步是验证产品是否正常以及是否允许用户订购。处理可能会调用产品目录服务,但必须传递用户上下文。这就是我要说的部分。

【问题讨论】:

为什么在通过队列推送时需要传递 jwt?只有授权客户端才能访问队列,您可以简单地在它们之间传递消息。队列的目的是让消息保持足够长的时间来构建松散耦合的微服务。但是,要通过 http 访问 api,您必须传递授权标头。 我要传递授权信息。用户已通过身份验证,这是真的,但我还需要他的角色、租户上下文等... 我还想要调用后续服务的能力,所以通过 jwt 也可以解决这个问题... 如果您真的想发送 Jwt 令牌,请增加到期时间(几分钟即可)。它应该能够承受队列不可用。传递令牌是可以的,只要它得到适当的保护并且它已经流过安全的队列通道。 【参考方案1】:

你有

    网关 -> MS1 -> Kafka -> Kafka 消费者 -> MS2 网关 -> MS2

在第二种情况下,MS2 代表用户行事,因此用户的 JWT 在这里有意义。

在第一种情况下,Kafka Consumer 只是同步 MS1 中已经发生的操作。它不代表外部用户行事。外部用户在这里没有任何控制权。在这个阶段,用户不能读或写任何错误的东西。用户交互在 MS1 本身结束。

因此,出于授权目的,Kafka Consumer 中不需要外部用户 JWT。但是,在消息中,您可以传递用户上下文(如用户名和其他相关详细信息)进行处理。根据这些信息,您需要决定是否继续执行订单。

但是,Kafka 消费者需要它自己的访问令牌,这些令牌将用于所有不同的用户订单。您需要在此处用于 Kafka 消费者和 MS2 之间通信的 OAuth 2.0 授权类型称为 "Client Credential" 授权类型。

在这里,消费者将使用适当的凭据和客户端 ID 直接与授权服务器联系以获取访问令牌

【讨论】:

听起来很合法,但是它需要 MS2 处理两种授权(角色)情况——一种来自外部 API(jwt),另一种来自“内部 api”——来自 kafka 侦听器的调用。我对吗?我的意思是 - 如果这是正确的方法,那没关系,只是想确定一下。 @redguy Spring OAuth 2.0 实现可以同时支持多种授权类型。并且它还支持客户端凭证授予类型 但是这种授权类型是否意味着不仅仅是“一些名字”? @redguy 每个授权类型都有一个单独的流程。不确定我是否理解您的询问。也许您应该看看我在回答中链接的 RFC。它将更加清晰 在接受答案之前,我必须阅读有关客户端凭据授予的更多信息。似乎它解决了我的部分问题 - 提供一致的身份验证并简化微服务配置。至于传递用户上下文 - 我决定在使用 client_credentials 授权调用时只传递 userId 和目标服务,这样的 userId 调用 auth-api 服务用于用户上下文。

以上是关于在微服务之间传递用户身份和授权的主要内容,如果未能解决你的问题,请参考以下文章

在微服务架构中组织授权的最佳实践?

在微服务架构中组织用户和身份验证

springcloudalibaba架构(31):SpringCloud实现用户信息在微服务之间传递(Feign和Dubbo)

如何在微服务和 API 网关架构中对不同的配置文件进行身份验证和授权

Quarkus:如何在微服务之间进行身份验证?

SpringBoot+SpringCloud实现登录用户信息在微服务之间的传递