如何授权微服务内部通信?

Posted

技术标签:

【中文标题】如何授权微服务内部通信?【英文标题】:How to Authorize micro-services internal communication? 【发布时间】:2019-11-02 22:12:24 【问题描述】:

我有多个微服务。客户端可以通过API网关调用,微服务之间也可以相互通信。

理想情况下,请求将来自拥有所有权限的用户的 API 网关。 在这里,我试图仅将所需的角色分配给用户,例如,如果用户(浏览器)需要来自微服务 A 的数据,那么只有该角色将提供给用户,如果内部微服务 A 需要来自 B(休息调用)的数据,那么该角色不应分配给用户。

需求:如何限制/授权微服务之间的内部通信,使只有授权的微服务才能调用其他微服务。

选项:

    将所有角色分配给用户,甚至用于内部通信(在所有通信中传递相同的令牌)。

    如果需要内部通信,则仅将面向用户的微服务角色分配给用户,然后每个微服务将充当其他微服务的用户,并在调用前生成自己的令牌。

    不允许微服务内部通信,而是从客户端的所有微服务和进程中获取所有数据。

上面或任何其他选项最好使用哪个选项?

【问题讨论】:

Propagate HTTP header (JWT Token) over services using spring rest template的可能重复 Offcource 传递令牌是一种选择,但随后使用需要所有角色。 【参考方案1】:

我会选择 2 号选项。对于服务内通信,后端服务(应用程序)将充当客户端并首先请求令牌 (/oauth/token)。为了验证这些令牌,所有服务都需要一种机制来验证这些令牌 (/oauth/check_token)。您可以为此使用Client Credentials Grant 类型。这些 /oauth/** 端点由 Spring 提供。要从一项服务向另一项服务发出 REST 请求,请使用 OAuth2RestTemplate 和 its not thread-safe。

在每个应用程序中,您都需要为各种端点定义安全保护规则。像这样的:

<sec:filter-security-metadata-source id="securityMetadataSource"
                                         request-matcher="ant"
                                         use-expressions="true">
        <sec:intercept-url pattern="/accounts/**" access="isFullyAuthenticated() and hasRole('PRIVATE_SERVICE')"/>
        <sec:intercept-url pattern="/members/member-details" method="GET" access="isFullyAuthenticated() and hasRole('PORTAL_USER')"/>

对于更多限制,您为每个应用程序(而不是每个应用程序实例)颁发自签名证书。在单个信任库中添加所有应用程序的公钥。在应用程序启动期间,让所有应用程序下载此信任库。此应用程序将只与它信任的应用程序对话。

【讨论】:

谢谢,我们可以使用一个通用的 jar 来进行令牌验证吗?而不是在所有微服务中添加相同的代码? 在这种特定情况下,令牌验证将通过CheckTokenEndpoint 进行。 Spring 公开了这个端点/oauth/check_token。每个应用程序都有自己唯一的客户端 ID(因此 RemoteTokenServices 配置会有所不同)并且每个应用程序都有不同的端点(因此安全配置会有所不同),这里似乎没有什么共同点。【参考方案2】:

我们混合使用选项 1 和 2。

如果用户调用一个 API,那么如果第一个网关调用服务 A,然后服务 A 调用服务 B,那么 A 将相同的 JWT 令牌传递给服务 B。

如果服务 A 中的计时器作业定期从服务 B 获取一些数据,则服务 A 也有其 JWT 令牌,通过该令牌调用服务 B。

【讨论】:

以上是关于如何授权微服务内部通信?的主要内容,如果未能解决你的问题,请参考以下文章

微服务内部通信

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

微服务内部通信时的 SSL 证书主机名问题

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

微服务中的授权 - 如何使用 ACL 处理域对象或实体级别的访问控制?

Docker 微服务架构 - 不同容器之间的通信