17

我正在研究使用 DDD+CQRS+EventSourcing 制作应用程序,但在弄清楚如何进行用户身份验证时遇到了一些麻烦。

用户本质上是我领域的一部分,因为他们对客户负责。我正在使用 ASP.NET MVC 4,我希望只使用 SimpleMembership。由于登录和授权用户是一个同步操作,那么在最终一致的架构中如何解决这个问题?

我是否必须推出自己的身份验证系统,在读取端保留非规范化身份验证表?如何处理这个安全性?我最终会在我的事件存储和我的视图表中存储密码哈希吗?

这么多问题,如果有人能解释一下,我将非常感谢:)

tldr; 您如何在 EventSource-applications 中进行用户身份验证?

4

3 回答 3

14

并非每个“域”或业务组件都必须使用 DDD 或 CQRS。在大多数情况下,用户信息真的很脏,所以你通常不能为此使用 DDD。其他域并不真正依赖于实际用户。通常有一个由各个域共享的相关 ID (UserId)。

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

于 2013-03-26T18:10:34.070 回答
12

对于我们的 MVC CQRS 应用程序,我们最初将所有与用户相关的信息保存在域中,就像有人提到的那样,有一个 RegisterUserCommand 和一个 UserRegisteredEvent。在将用户信息存储在域中之后,该事件被发布并在读取端获取,这也创建了一个用户并生成了所有密码哈希等。然后我们在读取端进行了身份验证:控制器将创建一个调用“读取模型身份验证服务”进行身份验证。

后来,我们最终完全重构了它。事实证明,我们需要访问用户相关信息来构建安全性以授权我们的命令,这是我们在命令处理端完成的(我们的应用程序是一个分布式应用程序,它向队列发送“即发即弃”异步命令,使用另一边的自主听众)。然后,安全组件需要引用我们的域来获取用户配置文件,这导致了繁琐的引用问题。

我们决定将用户安全内容放入一个单独的数据库中,我们认为该数据库更像是一个中心组件,而不是属于域或读取模型。我们仍然在域中维护用户配置文件相关信息并读取模型(例如职位、Twitter 帐户 URL 等),但所有与安全相关的内容,如密码哈希,都存储在这个中央数据库中。然后可以通过服务访问它,该服务对 MVC 和命令授权者都可用。

我们实际上不需要为这个重构更改 UI 中的任何内容,因为我们只是调用了服务来从 register user 命令处理程序中注册用户。如果你打算这样做,你需要在这里小心,使你的用户服务相关的操作是幂等的。这样您就可以让您的命令有机会在没有副作用的情况下重试,因为您正在更新 2 个信息源(ES 和用户数据库)。

最后,您当然可以将成员资格提供程序用于此中心组件,但这样做可能会存在缺陷。我们最终只写了自己的——这很简单。那篇文章链接到这个,它提供了一个很好的例子来说明如何实现它。

于 2013-03-27T10:38:34.750 回答
1

您应该考虑创建单独的实体,例如:访问者(刚刚访问您的站点)、用户(注册)、客户(购买了东西)等。尝试以这种方式拆分您的系统,即使它会导致一点数据冗余。磁盘空间不是问题,但独立修改系统不同组件的能力通常非常关键。

人们创建非规范化身份验证表只是为了扩展,并且仅当您的身份验证读取端是性能瓶颈时。如果不是 - 通常的第三范式是一种方法。

在 SimpleMembership 场景中,SimpleMembership 创建的所有表都可以视为“用户”聚合的快照。是的,他们会在您的事件存储中复制一些数据。您可能有以下事件:UserCreated、UserUpdated、UserAssignedToRole 等。

并且不要被该会员提供者的名称所欺骗。它不是那么简单,通常有很多你可以轻松生活的东西(取决于你的领域)。所以,也许你可以使用这样的东西:https ://gist.github.com/Kayli/fe73769f19fdff40c3a7

于 2013-03-27T00:57:04.397 回答