如何处理复合微服务请求中的验证?

时间:2017-03-23 16:01:34

标签: architecture microservices software-design distributed-transactions

考虑具有两个实体的应用程序:

  • User(包含基本用户数据,例如姓名)
  • Passport(包含身份验证凭据,即密码)

两个内部微服务:

  • UserService(负责创建和管理用户及其基本数据)
  • AuthService(负责用户身份验证和密码处理)

User实体属于UserServicePassport实体属于AuthService

这两个服务应该分开,因为它们可以解决截然不同的任务:配置文件数据身份验证

另外,请考虑我们有一个包含三个字段的注册表:

  • 电子邮件
  • 名称
  • 密码

此表单将触发对GatewayService的HTTP请求,该请求拦截对应用程序的所有请求,并将它们路由到内部微服务(或组合/聚合它们)。

现在,当网关服务收到包含所有表单数据的请求时,它需要执行以下操作:

  1. 致电UserService以创建新用户(它将以生成的userId回复)。
  2. 致电AuthService为新创建的用户创建护照。它需要步骤#1中收到的userId和原始请求中的password字段。
  3. 这看起来非常简单,但如果{2}在步骤2中不可用,会发生什么?我们需要以某种方式将这些请求分开!

    经典方法是使用最终一致性并通过异步调用创建AuthService实体(我们可以将此请求放入队列并在单独的服务中处理它)。为了做到这一点,我们将向Passport发送一个异步请求AuthServiceuserId,而不是步骤#2,因此步骤#1将立即返回响应客户端。

    但是,如果password字段格式不正确(中断验证规则)怎么办?验证逻辑仅出现在password中,因此在调用密码之前我们无法知道密码是否正确。现在,请求是异步处理的,因此我们无法回复用户并告诉他更正密码。

    那么,您如何正确处理微服务应用程序的分布式复合请求中的验证?

    1. 天真的解决方案是将验证逻辑移到AuthService本身,但这是一个糟糕的主意,因为它会使它变胖并且会从GatewayService泄漏业务逻辑。

    2. 另一个想法是提供一种额外的密码验证方法,并在步骤#1和#2之前调用它。它看起来像一个可行的解决方案,但它将迫使我们为我们的微服务中的每个业务方法提供两种方法,一种用于事先验证,一种用于实际操作。此外,验证和操作之间存在时间空间,因此在实际执行操作时,较早的正确值可能会变得不正确。

    3. 我们可以将表单拆分为两个以避免复合请求,并在询问个人数据并为他创建帐户后询问用户密码。但是,这可能会导致安全问题,其他用户可能会猜到下一个AuthService用户帐户。我们可以使用一些额外的安全令牌,但它会为服务引入奇怪的功能,并使整个设置更加复杂。

      此外,这种方法看起来像是试图逃避问题,您无法始终避免复合请求。

    4. 我们可以使用全面的分布式交易,例如2PC,但它会使系统变得非常复杂,并且首先会减少MSA的使用。

    5. 最后的想法是将这两种服务合并在一起,但在微服务架构中这样做是没有意义的。

3 个答案:

答案 0 :(得分:1)

这是我的想法

1. 用户服务 - 应负责

创建包含用户名,密码(散列),电子邮件和任何其他个人资料数据的用户

根据验证规则验证输入数据

使用密码验证用户

<强>优点

对简档数据的进一步说明很容易

在单个请求中查找并验证用户

用户相关的单一登录

2. 身份验证服务应仅负责根据用户服务的成功用户验证生成令牌

这些令牌应该用于生态系统中所有其他服务的进一步处理,并确保适当的授权

专业人士

将来需要用户身份验证和授权的服务可以独立工作,只需要安全令牌。

基于先前令牌生成令牌可以很容易,每次令牌即将到期时,用户无需输入用户名和密码。

答案 1 :(得分:0)

关于#5,我真的没有看到你在某种程度上通过合并到一个服务(第5点)来实现对原则的可怕违反,这是一种负责这两项任务的“UserManagementService”;即使可以说一个MS应该执行一项任务并且做得很好,这两者密切相关,恕我直言。

另一种选择是使UserService成为AuthService的同步客户端(负载均衡,带断路器,无论如何,以确保一个实例的可用性),这与在“正常”中注入密码验证的依赖性基本相同码。

如果这是一个绿色的事情并且你没有坚持这两种服务,一般来说,我会选择更简单的第一次实施,并抵制优化的冲动,因为这些往往是不成熟的,或者是无根据的承诺原则/教条的纯洁。你自己都知道你可以介绍的复杂性(2PC)加上你有你的要求(“因此我们无法回复用户并告诉他更正密码”)。

答案 2 :(得分:0)

我同意#5。这两个服务将具有许多依赖关系,因为访问UserService将始终与AuthService相关,并且它们可能访问相关数据。 如果将它们分开,则可能需要将其共享逻辑分开,例如生成护照。它可以在服务中具有从AuthService(在验证凭据之后)或从UserService(在注册之后)接收用户ID的操作。

同时处理缺少AuthService会引发有关其他方案的问题,例如,如果用户已经注册但无法登录,您如何处理?如果您显示错误消息,为什么不在注册时?..只是一个关于你的要求的更多想法的问题。

干杯