如何在微服务架构中处理认证问题

8

我目前正在阅读关于微服务的大量资料,但仍然不理解其中的一些部分。我画了以下图:

enter image description here

每个微服务都有两个访问方式:
  • REST:用于http使用
  • gRPC:用于内部/后台通信/交换

如果我想登录,只需向我的身份验证服务发送Http请求即可。但是如果我想访问需要您已经连接的Stuff服务呢?

假设用户想要显示数据库STUFF中可用的内容,则Stuff服务将首先通过与身份验证服务进行交换来检查已连接用户的“令牌”是否正确,然后返回物品或“需要登录请求”。

所以我不明白的是,如果每个需要已连接客户端的服务都需要与身份验证进行交换,那么它将创建巨大的互联网流量以检查每个用户请求...所以我考虑为每个服务制作一个身份验证服务,但由于我应该只有一个数据库,因此会减缓流量的是数据库吗?

另外,如果我理解正确,每个微服务都应该在单独的服务器上,而不是同一个服务器上?

我希望我表达清楚了,如果需要更多细节,请不要犹豫!

谢谢!

Max

编辑1

根据@notionquest的答案:

所以它应该更像那样,对吗?

enter image description here

此外,根据Peter的评论,每个服务都可以实现自己的中间件(如JWT),因此API网关只是一个“透传器”。然而,我认为每个服务在每次内部交换时都要进行令牌检查,这对我来说可能不是一件好事。 对于物品,它很容易,因为它只检查一次令牌。现在,假设用户得到了物品,他选择了一个并想要购买它。然后,“购买服务”将调用物品服务以验证该项目的价格,但是...它将不得不检查用户令牌,因为物品是“受身份验证访问”的,这意味着“购买”服务和“物品”服务都要检查令牌,这增加了额外的检查。 我考虑过服务之间的内部保证访问,但这值得吗? 也许你说要为每个服务实现中间件,因为它们具有REST访问,但API网关会破坏拥有REST访问的想法。

2
不要低估单个authz/authn服务的处理能力。实际上,它只是通过主键查找单个数据库行。一种流行的替代方案是JWT。但在你加入微服务队列之前,请注意它们解决了组织问题,但也创造了技术问题--很多问题。不要因为它现代就去做。 - Peter
谢谢你的回答!我这么做并不是因为它现代化,而是因为我有一个真正的需求:) 我了解JWT并且已经在单体应用中使用过它,但是仍然需要在每个服务之间共享进行JWT检查的服务。我只是担心互联网流量交换,我不想让一个服务得到太多请求而减慢其他服务的速度 :/ - Emixam23
1
JWT 是加密签名的,特别是为了让你无需向任何人进行检查而设计的。它们是自包含的证明。 - Peter
@Peter 根据你的回答和notionquest的想法,做了些小更新。 - Emixam23
https://dev.to/s2agrahari/authentication-between-microservices-part-i-3dpp - Suraj
2个回答

9
这个问题有多种解决方案。其中一个解决方案是API 网关模式
  1. 第一个请求发送到 API 网关
  2. API 网关对请求进行身份验证和授权
  3. 身份验证信息存储在缓存数据库中,例如 Redis、Memcache 等,并设置过期时间
  4. 返回保存的访问令牌给客户端
  5. 客户端可以在一段时间内(即令牌有效期)使用保存的访问令牌进行后续调用
  6. 令牌过期后,API 网关将对其进行身份验证并向客户端共享新令牌
  7. 此解决方案将减少每个请求的身份验证需求并提高性能
API 网关是所有服务的单一入口点。因此,您可能不需要为每个服务单独设置缓存。
请参考此页面中的图表。

谢谢您的回答。这意味着每个服务都应该有它自己的令牌缓存吗?因此,它不必与身份验证服务通信。 - Emixam23
更新了答案。API 网关是所有服务的单一入口点,因此您可能不需要为每个服务单独设置缓存。 - notionquest
好的,我明白了!但是现在,API网关必须处理所有请求,这似乎变成了单体应用的方式,不是吗? - Emixam23
2
不,这不是一个单块应用程序。它是所有服务前面的一个附加层,用于执行常见任务,如身份验证、聚合等。如果您能阅读完整的博客,我认为您会更好地理解。 - notionquest
我根据你的回答和彼得的回答进行了一点更新。 - Emixam23

5
除了@notionquest的答案之外,还有另一种方法不涉及API网关;
您可以在所有服务之间共享 SESSION_SECRET ,因此您的身份验证服务的唯一任务是针对数据库验证用户名和密码,然后使用 SESSION_SECRET 加密此信息并返回{{link1:jwt token}}。 所有其他服务都不需要与身份验证服务交互,而只需检查jwt令牌是否有效(可以解密)使用SESSION_SECRET
然后您有另外两个选项;
  1. 将所需的所有用户数据存储在令牌中-这将增加从客户端到微服务的传输数据量。根据此信息的大小,这可能具有限制性

  2. 您可以仅存储userId,并根据需要为每个微服务请求附加数据,具体取决于数据的频率/大小,这将产生您所描述的问题。

请注意,您并不总是能够使用这种方法,但根据您的特定情况和要求,考虑到此架构可能会有所帮助。
请记住,旋转SESSION_SECRET可能会有些棘手(尽管出于安全原因是必要的)。AWS刚刚推出了一个名为AWS Secrets Manager的服务,因此简化事情的一个想法是让您的微服务定期查询此类服务以获取当前有效的SESSION_SECRET,而不是将这些值硬编码或作为环境变量。

感谢您的编辑和回答。我觉得,通过您提供的所有答案(而且由于我根本不从事安全编程),最终每种方法都没有得到保障。它们都可以被轻松地反向工程化 :/ - Emixam23
欢迎,@Emixam23。你能详细解释一下为什么你认为它不安全吗? - Renato Gama
1
没错。但对于大多数网站来说都是如此。例如,如果有人获得了您的会话cookie访问权限,那么任何人都可以冒充您。这就是为什么人们目前使用https。但我理解您的担忧。 - Renato Gama
他们可以这样做,但窃听者无法解密它们,因此无法访问其内容。 - Renato Gama
1
如果您想拥有私有微服务(即它们不对外开放),那么您应该选择API网关。亚马逊AWS为此提供了一项服务,您可能需要查看一下。 - Renato Gama
显示剩余2条评论

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