对于我们的 MVC CQRS 应用程序,我们最初将所有与用户相关的信息保存在域中,就像有人提到的那样,有一个 RegisterUserCommand 和一个 UserRegisteredEvent。在将用户信息存储在域中之后,该事件被发布并在读取端获取,这也创建了一个用户并生成了所有密码哈希等。然后我们在读取端进行了身份验证:控制器将创建一个调用“读取模型身份验证服务”进行身份验证。
后来,我们最终完全重构了它。事实证明,我们需要访问用户相关信息来构建安全性以授权我们的命令,这是我们在命令处理端完成的(我们的应用程序是一个分布式应用程序,它向队列发送“即发即弃”异步命令,使用另一边的自主听众)。然后,安全组件需要引用我们的域来获取用户配置文件,这导致了繁琐的引用问题。
我们决定将用户安全内容放入一个单独的数据库中,我们认为该数据库更像是一个中心组件,而不是属于域或读取模型。我们仍然在域中维护用户配置文件相关信息并读取模型(例如职位、Twitter 帐户 URL 等),但所有与安全相关的内容,如密码哈希,都存储在这个中央数据库中。然后可以通过服务访问它,该服务对 MVC 和命令授权者都可用。
我们实际上不需要为这个重构更改 UI 中的任何内容,因为我们只是调用了服务来从 register user 命令处理程序中注册用户。如果你打算这样做,你需要在这里小心,使你的用户服务相关的操作是幂等的。这样您就可以让您的命令有机会在没有副作用的情况下重试,因为您正在更新 2 个信息源(ES 和用户数据库)。
最后,您当然可以将成员资格提供程序用于此中心组件,但这样做可能会存在缺陷。我们最终只写了自己的——这很简单。那篇文章链接到这个,它提供了一个很好的例子来说明如何实现它。