微服务认证策略

176

我在为微服务架构选择一个良好/安全的身份验证策略上遇到了困难。我在这个主题上找到的唯一一个SO帖子是这个:Single Sign-On in Microservice Architecture

我的想法是,在每个服务中(例如认证、消息传递、通知、个人资料等),都有对每个用户的唯一引用(很自然地使用他的user_id),并且有可能获取当前用户的id如果已经登录。

从我的研究中,我看到有两种可能的策略:

1. 共享架构

Shared architecture

在这种策略中,认证应用程序是其他服务之一。但是每个服务都必须能够进行转换session_id => user_id,因此它必须非常简单。这就是为什么我考虑Redis,它将存储键值session_id:user_id

2. 防火墙架构

Firewall architecture

在这种策略中,会话存储并不重要,因为它仅由认证应用程序处理。然后user_id可以转发给其他服务。我考虑了Rails + Devise(+ Redis或mem-cached,或cookie存储等)但是有很多可能性。唯一重要的事情是Service X永远不需要验证用户。


这两种解决方案在以下方面有何比较:

  • 安全性
  • 健壮性
  • 可伸缩性
  • 易用性

或者你会建议我在这里没有提到的其他解决方案吗?

我更喜欢解决方案#1,但是还没有找到太多默认实现,可以确保我朝着正确的方向前进。


1
请问您能否提供更多关于您想要实现的细节?在第一种情况下,认证是针对Redis进行的,还是在服务本身中进行的?第二个图中缺少Redis,这是有意为之吗? - Plamen Petrov
我已添加了一些信息,请告诉我这是否仍不清楚。谢谢! - Augustin Riedinger
我对这个解决方案很好奇,但我仍然不明白它在实践中如何工作。你知道在哪里可以找到一些标准的实现吗? - Augustin Riedinger
@AugustinRiedinger,感谢您的分享。我也正在采取渐进式的方式将我的单体Web应用程序拆分为微服务。在您的情况下,服务1-n是无状态还是有状态的?如果它们是有状态的,您是否考虑在每个服务中管理会话?谢谢。 - Manchanda. P
如果您为每个服务使用不同的会话存储,那么要么用户必须在每个服务中都登录,要么您需要设置一个流程,对于一个注册,将用户注册到每个其他服务中,其最基本的形式是共享会话ID,这对应于策略#1。或者我错过了什么? - Augustin Riedinger
显示剩余2条评论
5个回答

75

1
谢谢,很清楚。我发现这篇文章非常好,几乎分解了相同的解决方案:http://dejanglozic.com/2014/10/07/sharing-micro-service-authentication-using-nginx-passport-and-redis/ - Augustin Riedinger
19
你的回答很好,但是API网关生成的令牌(可能在其内部或身份验证微服务中)如何被一个随机的微服务处理,这个微服务的目的不是认证,并且可能没有OAuth管理在其业务代码内部? - mfrachet
例如,您可以使用Netflix Zuul将在网关中接收到的令牌发送到所有服务,它们将了解用户信息。http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-security-oauth2 - Tiarê Balbi
请查看此文章,了解如何在微服务中使用OAuth控制用户身份:http://nordicapis.com/how-to-control-user-identity-within-microservices/ - Declan Whelan
2
OAuth更多的是关于授权一个系统访问另一个系统中保存的用户数据。对我来说,这似乎是使用SAML的一个很好的案例。 - Rob Grant
显示剩余2条评论

12
简短回答:使用基于令牌的Oauth2.0身份验证,可用于任何类型的应用程序,如Web应用程序或移动应用程序。对于Web应用程序,涉及的步骤序列将是:
  1. 对ID提供程序进行身份验证
  2. 在cookie中保留访问令牌
  3. 访问Web应用程序中的页面
  4. 调用服务
下面的图表描述了所需的组件。这种将Web和数据API分离的架构将提供良好的可扩展性、弹性和稳定性。

enter image description here


AWS Lambda不会变得“冷”并需要时间启动吗?这会使登录变慢,不是吗? - Taku
@tsuz,AWS现在在Lambda中引入了并发功能,您可以预留并发。通过这种方式,您可以解决冷启动问题。https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html - Sandeep Nair
我很想在几年前就看到这个答案,它非常简单易懂地解释了微服务架构如何通过编排独立的身份验证和授权微服务来访问其他服务。 - brayancastrop
@Sandeep,我认为你指的是“预置并发”而不是“保留”。 - Anil Kumar

8
您可以使用JWT令牌避免在后端存储会话信息。
以下是使用OAuth 2.0OpenID Connect的示例。我还将用户名和密码登录添加到答案中,因为我假设大多数人也将其作为登录选项添加。 enter image description here这是解决方案的建议组件:
  1. 账户服务:一个微服务,负责用户创建和身份验证。可以有 Google、Facebook 或常规的用户名和密码验证端点——登录、注册端点。 在注册时——通过注册端点或首次使用 Google/Facebook 登录,我们可以将用户信息存储在数据库中。 当用户成功使用其中任何一种选项登录后,我们在服务器端使用相关用户数据(如 userID)创建 JWT 令牌。为了避免篡改,我们使用我们定义的令牌密钥(一个字符串)进行签名。 该令牌应作为 httpOnly cookie 与登录响应一起返回。出于安全考虑,建议仅使用 https。就 OpenID 连接规范而言,该令牌将是 ID 令牌。

  2. 客户端 Web 应用程序:作为 httpOnly cookie 接收签名的 JWT,这意味着 JavaScript 代码无法访问此数据,并且从安全角度来看是推荐的。在向服务器或其他微服务发送后续请求时,我们将 cookie 附加到请求中(在 axios 中,这意味着使用 withCredentials: true)。

  3. 需要通过令牌对用户进行身份验证的微服务: 这些服务验证 JWT 令牌的签名,并使用提供给签名令牌的相同密钥读取它。然后,它们可以访问存储在令牌上的数据,如 userID,并获取有关用户的其他信息或执行任何其他逻辑。请注意——这不是用于授权,而是用于身份验证。对于此目的,我们有刷新令牌和访问令牌,它们超出了问题的范围。

最近我创建了一份详细的指南,专门讨论这个主题,希望能对某些人有所帮助: https://www.aspecto.io/blog/microservices-authentication-strategies-theory-to-practice/


2

另一个架构视角是使用nuget-package(库),它实际上执行身份验证/令牌验证。每个微服务将使用nuget-package。

另一个好处是没有代码重复。


-5

您可以使用身份验证服务器4进行认证和授权

必须使用防火墙架构,以便更好地控制安全性、稳健性、可伸缩性和易用性


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