微服务架构中的单点登录

62

我正在尝试设计一个全新的项目,它将拥有多个服务(提供数据)和 web 应用程序(提供 HTML)。我已经了解了微服务,它们看起来很适合。

问题在于如何实现 SSO(单点登录)。我希望用户只需认证一次就可以访问所有不同的服务和应用程序。

我可以想到几种方法:

  1. 添加身份认证服务和应用程序。任何具有受保护资源的服务都会与身份认证服务通信,以确保其凭据有效。如果无效,它将重定向用户进行身份验证。

  2. 使用像 OpenID 这样的 Web 标准,并让每个服务处理自己的身份验证。这意味着用户需要单独授权每个服务/应用程序,但之后将是 SSO。

如果有其他想法,我很乐意听取。如果特定的 PaaS(例如 Heroku)有专有解决方案,那也可以接受。


通过阅读这个,我猜测没有官方标准的方法来解决这种问题? - Augustin Riedinger
1
你说得对。我正在使用自己的OAuth提供程序来获取SSO结果,但这不是唯一的方法。 - Ido Ran
1
我偶然发现了这个帖子(以及许多其他网站)。我发现以下两个网站在这方面非常有用: https://medium.facilelogin.com/securing-microservices-with-oauth-2-0-jwt-and-xacml-d03770a9a838 http://nordicapis.com/how-to-control-user-identity-within-microservices/ - Yogi
2个回答

51
在我的前一份工作中,我们在实施微服务架构时决定采用最佳方案之一,即 #1 添加身份认证服务并通过它授权服务访问。在我们的情况下,这是通过令牌完成的。如果请求带有授权令牌,那么如果它是用户会话与服务的第一个调用,则我们可以使用身份服务验证该令牌。一旦令牌被验证,它就会保存在会话中,因此用户会话中的后续调用无需进行额外的调用。如果需要刷新该会话中的令牌,还可以创建定期作业。
在这种情况下,我们正在使用 OAuth 2.0 端点进行身份验证,并将令牌添加到对我们域的调用的 HTTP 标头中。所有服务都从该域路由,因此我们可以从 HTTP 标头中获取令牌。由于我们都是同一应用程序生态系统的一部分,因此最初的 OAuth 2.0 授权将列出用户将为其帐户授权的应用程序服务。
此方法的另一个补充是,身份服务将提供代理客户端库,该库将添加到 HTTP 请求过滤器链中并处理向服务的授权过程。服务将配置为从身份服务中消耗代理客户端库。由于我们正在使用 Dropwizard,因此该代理将成为 Dropwizard 模块,引导过滤器到正在运行的服务进程中。只要接口没有发生重大变化,这就使得依赖服务可以轻松地消费有补充的客户端侧更新的身份服务更新。
我们的部署架构分布在 AWS 虚拟私有云 (VPC) 和我们自己公司的数据中心之间。OAuth 2.0 认证服务位于公司的数据中心,而所有应用服务都部署到 AWS VPC 上。
希望我们采取的方法对您的决策有所帮助。如果您有其他问题,请告诉我。

即使我也遇到了相同的情况,但在我的情况下,我有许多微服务,但我不希望用户明确地授予权限(假设我使用Oauth)给其他微服务,例如:在电子商务网站上,如果用户在主应用程序中经过身份验证,我不希望用户明确地授权购物车应用程序、建议应用程序(这对最终用户来说应该是无缝的)。我们是否可以使用Oauth或SAML实现这一点? - Lohith MV
1
“所有服务都从该域名路由”是什么意思? - wonder
谢谢你的建议,我根据你的提示实现了我的单点登录。这是我对你在评论中提出的方法的解释的视频:https://www.youtube.com/watch?v=r7FAuAlKIqY&t=36s - Cokorda Raka
感谢您提供的出色文章。在这种情况下,如何处理每个服务的会话失效? - Ankit Kumar
我认为服务在与认证服务器进行初始验证后应该使用自己的会话 cookie。重复使用认证服务器的令牌会添加一些不必要的依赖关系。如果认证服务器更改其令牌的格式,而这些令牌无法再适应服务的会话存储,则会怎样呢? - xuma202

41

Chris Sterling已经解释了标准认证实践并且这很有道理。出于一些实际原因,我想在这里提出另一个想法。

我们实现了认证服务和多个其他微服务,这些微服务依赖于授权服务器来授权资源。在某个时候,由于与认证服务器之间的往返次数过多,我们遇到了性能问题,当微服务的数量增加时,授权服务器的可扩展性也成为了问题。我们稍微改变了架构以避免往返次数过多。

只需使用凭据联系一次授权服务器,它将根据私钥生成令牌。相应的公钥将安装在每个客户端(微服务服务器)中,客户端可以在不与授权服务器通信的情况下验证认证密钥。密钥包含生成时间和在微服务中已安装的客户端实用程序将进行有效性检查。尽管这不是标准实施方式,但我们在这种模式下取得了相当不错的成功,特别是当所有微服务都在内部托管时。


3
我认为你描述的内容已经被Chris完成了,正如他所说的:“它被保存在会话中,因此用户会话中的后续调用不需要进行额外的调用。”也许我错了。 - Augustin Riedinger
7
由于端点的无状态特性,将数据保存在会话中可能不具有可扩展性或不被推荐。在我的方法中,它永远不会保存任何东西,只是使用公钥密码学来避免与认证服务器的往返交互。 - kamoor
6
那你会如何处理会话过期? - Constantinos
3
或者令牌撤销? - neverfox
1
我不明白之前提到的这种方法如何处理会话过期/撤销。 - Ankit Kumar
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接