事件溯源应用中的用户认证

17

我正在研究使用DDD+CQRS+EventSourcing构建应用程序,并且我在思考如何进行用户认证方面遇到了一些问题。

由于用户对客户负有责任,因此他们本质上是我的领域的一部分。我使用ASP.NET MVC 4,并且打算只使用SimpleMembership。由于登录和授权用户是同步操作,在一个事件上下文中如何处理这种情况呢?

我是否需要自己编写身份验证系统,将规范化的身份验证表保存在读取端?如何处理其安全性?我最终会将密码哈希存储在事件存储和视图表中吗?

有太多问题,如果有人能解答一些,我将不胜感激 :)

tldr; 事件源应用程序中如何进行用户认证?


据我所知,您可以像在基于消息的系统中一样进行操作。您似乎混淆了授权和认证。您想要保护什么? - Yves Reynhout
我并没有混淆它们,我确实在询问两者 :) 看起来我的主要问题是我不知道消息传递系统中如何完成它 ;) - tuxbear
3个回答

14

并非所有的“域”或业务组件都必须使用DDD或CQRS。在大多数情况下,用户信息真的很差,因此通常不会使用DDD来处理它。其他领域并不真正依赖于实际用户。通常有一个相关id(UserId)被各个领域共享。

如果在您的系统中使用消息传递,则一种选项是在没有CQRS的情况下注册和管理用户,然后发送命令(RegisterUser { UserId })。这将发布事件“用户已注册”。其他域可以监听此事件以启动任何所需的工作流程或AR。


2
我支持这种想法。并不是非得全盘采用CQRS,可以根据情况选择使用。对我们而言,我们会验证用户身份并颁发一个令牌,然后将该令牌分配到每个命令的头部,以确保用户具有正确的访问级别和凭证,在命令的上下文中执行特定操作。 - Sarmaad
4
谢谢!我认为这实际上是我要找的答案。我本来就在考虑这个解决方案,但是将数据存储在事件存储器和数据库表中似乎有点不妥。我也担心重放事件以恢复状态的能力,因为这是我探索事件溯源的唯一原因。同时,将两种架构并排使用也会带来一些认知负担。 - tuxbear

12
对于我们的MVC CQRS应用程序,我们最初将所有与用户相关的信息保留在域中,像某些人提到的那样,有一个RegisterUserCommand和一个UserRegisteredEvent。存储了用户信息后,该事件被发布并在读取端接收,该读取端还创建了一个用户,并生成了所有密码散列值等。然后我们在读取端进行身份验证:控制器会调用“读取模型认证服务”进行身份验证。
后来,我们完全重构了这个方案。事实证明,我们需要访问与用户相关的信息来为授权我们的命令建立安全性,我们在命令处理侧完成了这项工作(我们的应用程序是将“火而忘”的异步命令发送到队列中,队列另一侧有一个自治监听器)。然后安全组件需要引用我们的域去获取用户配置文件,这就导致了引用问题。
我们决定将用户安全性内容放入一个单独的数据库中,我们认为这更像是一个中央组件,而不是属于域或读取模型。我们仍然在域和读取模型中维护与用户配置文件相关的信息(例如职位、Twitter账户URL等),但所有与安全相关的内容,如密码散列值,则存储在此中央数据库中。然后可以使用服务访问该数据库,该服务可供MVC和命令授权者使用。
实际上,我们不需要更改UI来进行这个重构,因为我们只需调用服务从“注册用户命令处理程序”注册用户即可。如果您采用这种方式,您需要小心,使您的用户服务相关操作具有幂等性。这是为了让您的命令有机会在不产生副作用的情况下重试,因为您正在更新2个信息源(ES和用户数据库)。

当然,你可以使用成员资格提供程序来作为这个中心组件的解决方案,但是这种方法可能存在缺陷。我们最终选择编写自己的组件 - 这很容易做到。该文章链接到此处,提供了一个实现示例。


谢谢!我也会选择这条路,很高兴能从有实际经验使用这些结构的人那里获得一些建议。ES让我着迷的是利用旧信息构建新功能的能力。将域数据存储为事件对您是否有价值? - tuxbear
1
是的,因为这意味着您可以通过重放ES来重新生成安全性内容。 - jacderida
你所描述的只是使用一个额外的投影来处理你的领域事件。这真的非常容易,谢谢!因此,使用实时数据或陈旧数据只取决于何时将读模型与事件同步,没有其他更多的东西... - inf3rno

1
您应该考虑创建各种不同的实体,如:访问者(刚访问您的网站),用户(注册过),客户(购买了某些东西)等。即使会导致一些数据冗余,也要尝试以此方式拆分系统。磁盘空间不是问题,但通常能够独立修改系统的不同组件非常关键。
人们只为了扩展而创建非规范化的授权表,仅在您的授权读取方面出现性能问题时才这样做。如果没有 - 通常采用第三正常形式。
在SimpleMembership场景中,由SimpleMembership创建的所有表都可以视为“用户”聚合的快照。是的,它们将在您的事件存储中重复一些数据。您可能会有像UserCreated,UserUpdated,UserAssignedToRole等事件。
不要被该成员资格提供程序的名称所欺骗。它并不简单,而且通常有很多您可以轻松不用的东西(取决于您的领域)。所以,也许您可以使用类似于https://gist.github.com/Kayli/fe73769f19fdff40c3a7的东西。

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