【问题标题】:Microservice to Microservice calls, authorization from a queue message微服务到微服务调用,来自队列消息的授权
【发布时间】:2017-03-20 10:02:15
【问题描述】:

上下文:我正在创建一个云平台,以支持使用 SSO 的多个应用程序。我通过 Keycloak Spring Security Adapter 使用 Keycloak 进行身份验证Netflix Zuul 进行授权(API 网关)。

每个微服务都需要一个 Authorization 标头,其中包含一个有效的 JWT,它将使用用户名(子)来处理请求。每个微服务到微服务的调用都应该首先通过 Netflix Zuul,传递 Authorization 标头以维护无状态验证。该策略允许每个微服务知道谁是间接调用微服务的用户(子)。

问题/问题 1:如果从队列消息中调用微服务会发生什么?我的一个想法是将与消息 + userInfo 相关的信息存储在队列中,并创建一个专用的微服务来处理这种消息,通过这种方法,这个特殊的微服务应该从队列中读取 userInfo 并处理消息.

更新 1:根据来自另一个论坛的电子邮件回复,将 JWT 存储在队列中并不是一个好主意,因为它很容易被挖掘。

问题/问题 2: 但是,如果之前的特殊微服务想要调用另一个期望在标头中接收 JWT 的普通微服务,会发生什么?这个特殊的微服务是否应该自己创建一个JWT来模拟用户并能够调用常规微服务?

我认为的另一个解决方案是将原始 JWT 存储在队列中,但是,如果队列稍后调用特殊微服务会发生什么?就在 JWT 不再有效(过期)并且被调用的微服务将拒绝请求之后?

可能的解决方案:(根据 João Angelo 的讨论更新,见下文)

我应该对来自我的用户(授权代码流)和我的服务(客户端凭据授予)的请求进行身份验证,这两个请求都应该在负载中包含用户信息。当它来自用户的请求时,我需要验证有效负载用户信息是否与 JWT 声明匹配。当请求来自服务时,我只需要信任该服务(只要它在我的控制之下)。

非常感谢您的帮助。谢谢。

【问题讨论】:

  • “根据来自另一个论坛的电子邮件回复” - 哪个论坛,您可以提供链接吗?

标签: spring-security jwt microservices netflix-zuul keycloak


【解决方案1】:

免责声明:我从未使用过 Keycloak,但标签 wiki 说它符合 OAuth2,所以我相信这些信息。


从高层次来看,您似乎有两个要求:

  1. 验证最终用户在使用您的系统时触发的操作。
  2. 验证系统在未知时间触发的操作,并且最终用户无需在线。

您已经遇到了第一个,依靠基于令牌的身份验证系统,第二点我会做完全相同的事情,唯一的区别是令牌将使用OAuth2 客户端凭据授权,而不是针对存在最终用户的场景的其他授权。

(来源:Client Credentials Grant

在您的情况下,Keycloak 将扮演 Auth0 的角色,您的客户端应用程序是微服务,可以维护用于在授权服务器中对自己进行身份验证并获取访问令牌的客户端机密。

需要记住的一点是,如果您的系统依赖于 sub 声明的功能远不止身份验证和授权,那么您可能需要进行一些调整。例如,我见过执行操作 A 需要知道它针对用户 X 和 Y 的系统,但操作的有效负载只接收到用户 Y 并假设用户 X 是当前经过身份验证的主体。这在一切都是同步的情况下工作得很好,但是仅仅通过切换有效负载来指定两个用户将意味着该操作可以由系统身份验证的主体异步完成。

【讨论】:

  • 你好 João,我明白了,所以,1) 微服务​​应该总是期望来自用户或其他服务的 JWT。我刚刚进行了测试,发现微服务的 JWT 与用户之间的一些差异不包含声明,并且它包含一个额外的“clientId”字段,因此,如果 JWT 包含“ clientId" 不是用户而是服务。或者,我可以在“aud”字段中,如果“aud”对应于客户端名称来验证用户,它是一个用户,如果不是,是另一个服务。
  • 2) 如果我确定调用来自用户“aud”或“clientId”我可以使用“sub”或“preferred_username”验证有效负载字段,以确保有效负载的值对应于正在执行操作的用户。但是,在服务的情况下,我只需要信任有效负载中指定的用户?
  • 是的,这是一种方法,当输入来自用户时验证输入,以确保他们不会试图伪造其他用户并在输入来自您自己的服务时信任它。假设所有微服务都在您的控制之下,这似乎是一种合适的方法。它似乎也比存储访问令牌和/或刷新令牌更简单,这样即使用户离线也可以稍后执行调用。
【解决方案2】:

一种常见的设置是使用API gateway 来验证所有传入请求的 JWT。 API 网关验证 JWT 的签名(或为加密的 JWT 解密),检查到期时间等,并从中提取范围和用户 ID(子)。

然后它将范围与每个微服务的一组定义范围进行比较,如果范围提供用户(主体)访问权限,则将请求转发到微服务。用户 ID(JWT 中的子)以及存储在 JWT 中的其他所需信息被放置在自定义请求标头中,例如 X-IGNACIO-SUBJECT

【讨论】:

  • 问题也是关于服务到服务的通信。因为不是集群中的每个服务都不允许调用另一个服务。因此,您的服务也需要一些身份验证和授权机制,例如 istio istio.io) 之类的策略,或者为每个服务使用 jwt:stormpath.com/blog/microservices-jwt-spring-boot
【解决方案3】:

正如您所说,您的微服务使用 JWT 进行身份验证,始终通过网关,这样您实际上可以使用 FEIGN CLIENT 的概念。 Feign as rest client example.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-08
    • 2019-03-15
    • 2020-09-27
    • 2016-03-27
    • 1970-01-01
    • 2020-03-01
    • 2018-12-28
    • 2016-07-17
    相关资源
    最近更新 更多