考虑具有两个实体的应用程序:
User
(包含基本用户数据,例如姓名)Passport
(包含身份验证凭据,即密码)两个内部微服务:
UserService
(负责创建和管理用户及其基本数据)AuthService
(负责用户身份验证和密码处理) User
实体属于UserService
且Passport
实体属于AuthService
。
这两个服务应该分开,因为它们可以解决截然不同的任务:配置文件数据和身份验证。
另外,请考虑我们有一个包含三个字段的注册表:
此表单将触发对GatewayService
的HTTP请求,该请求拦截对应用程序的所有请求,并将它们路由到内部微服务(或组合/聚合它们)。
现在,当网关服务收到包含所有表单数据的请求时,它需要执行以下操作:
UserService
以创建新用户(它将以生成的userId
回复)。AuthService
为新创建的用户创建护照。它需要步骤#1中收到的userId
和原始请求中的password
字段。这看起来非常简单,但如果{2}在步骤2中不可用,会发生什么?我们需要以某种方式将这些请求分开!
经典方法是使用最终一致性并通过异步调用创建AuthService
实体(我们可以将此请求放入队列并在单独的服务中处理它)。为了做到这一点,我们将向Passport
发送一个异步请求AuthService
和userId
,而不是步骤#2,因此步骤#1将立即返回响应客户端。
但是,如果password
字段格式不正确(中断验证规则)怎么办?验证逻辑仅出现在password
中,因此在调用密码之前我们无法知道密码是否正确。现在,请求是异步处理的,因此我们无法回复用户并告诉他更正密码。
那么,您如何正确处理微服务应用程序的分布式复合请求中的验证?
天真的解决方案是将验证逻辑移到AuthService
本身,但这是一个糟糕的主意,因为它会使它变胖并且会从GatewayService
泄漏业务逻辑。
另一个想法是提供一种额外的密码验证方法,并在步骤#1和#2之前调用它。它看起来像一个可行的解决方案,但它将迫使我们为我们的微服务中的每个业务方法提供两种方法,一种用于事先验证,一种用于实际操作。此外,验证和操作之间存在时间空间,因此在实际执行操作时,较早的正确值可能会变得不正确。
我们可以将表单拆分为两个以避免复合请求,并在询问个人数据并为他创建帐户后询问用户密码。但是,这可能会导致安全问题,其他用户可能会猜到下一个AuthService
用户帐户。我们可以使用一些额外的安全令牌,但它会为服务引入奇怪的功能,并使整个设置更加复杂。
此外,这种方法看起来像是试图逃避问题,您无法始终避免复合请求。
我们可以使用全面的分布式交易,例如2PC,但它会使系统变得非常复杂,并且首先会减少MSA的使用。
最后的想法是将这两种服务合并在一起,但在微服务架构中这样做是没有意义的。
答案 0 :(得分:1)
这是我的想法
1. 用户服务 - 应负责
创建包含用户名,密码(散列),电子邮件和任何其他个人资料数据的用户
根据验证规则验证输入数据
使用密码验证用户
<强>优点强>
对简档数据的进一步说明很容易
在单个请求中查找并验证用户
用户相关的单一登录
2. 身份验证服务应仅负责根据用户服务的成功用户验证生成令牌
这些令牌应该用于生态系统中所有其他服务的进一步处理,并确保适当的授权
专业人士
将来需要用户身份验证和授权的服务可以独立工作,只需要安全令牌。
基于先前令牌生成令牌可以很容易,每次令牌即将到期时,用户无需输入用户名和密码。
答案 1 :(得分:0)
关于#5,我真的没有看到你在某种程度上通过合并到一个服务(第5点)来实现对原则的可怕违反,这是一种负责这两项任务的“UserManagementService”;即使可以说一个MS应该执行一项任务并且做得很好,这两者密切相关,恕我直言。
另一种选择是使UserService成为AuthService的同步客户端(负载均衡,带断路器,无论如何,以确保一个实例的可用性),这与在“正常”中注入密码验证的依赖性基本相同码。
如果这是一个绿色的事情并且你没有坚持这两种服务,一般来说,我会选择更简单的第一次实施,并抵制优化的冲动,因为这些往往是不成熟的,或者是无根据的承诺原则/教条的纯洁。你自己都知道你可以介绍的复杂性(2PC)加上你有你的要求(“因此我们无法回复用户并告诉他更正密码”)。
答案 2 :(得分:0)
我同意#5。这两个服务将具有许多依赖关系,因为访问UserService将始终与AuthService相关,并且它们可能访问相关数据。 如果将它们分开,则可能需要将其共享逻辑分开,例如生成护照。它可以在服务中具有从AuthService(在验证凭据之后)或从UserService(在注册之后)接收用户ID的操作。
同时处理缺少AuthService会引发有关其他方案的问题,例如,如果用户已经注册但无法登录,您如何处理?如果您显示错误消息,为什么不在注册时?..只是一个关于你的要求的更多想法的问题。
干杯