Пользователь Auth в приложениях EventSourcing

Я занимаюсь разработкой приложения с помощью DDD + CQRS + EventSourcing, и у меня есть некоторые проблемы с выяснением того, как сделать пользовательский аут.

Пользователи являются неотъемлемой частью моего домена, так как они отвечают за клиентов. Я использую ASP.NET MVC 4, и я хотел просто использовать SimpleMembership. Поскольку вход в систему и авторизация пользователей являются синхронной операцией, как это решаться в последовательной согласованной архитектуре?

Нужно ли мне рулон моей собственной системы auth, где я сохраняю денормализованные таблицы аутентификации на стороне чтения? Как справиться с этим? Смогу ли я сохранить хэши паролей как в моем хранилище событий, так и в моих таблицах представления?

Так много вопросов, если кто-нибудь может пролить свет, я был бы очень благодарен:)

TL;DR; Как вы выполняете аутентификацию пользователя в приложениях EventSource?

Ответ 1

Не каждый "домен" или бизнес-компонент должен использовать DDD или CQRS. В большинстве случаев информация пользователя очень грубая, поэтому вы обычно не можете использовать DDD для этого. Другие домены действительно не зависят от фактического пользователя. Обычно есть идентификатор корреляции (UserId), который делится между различными доменами.

При использовании обмена сообщениями в вашей системе одним из вариантов является регистрация и управление пользователями без CQRS, а затем отправьте команду (RegisterUser {UserId}). Это опубликует событие, зарегистрированное пользователем. Другие домены могут прослушивать это событие для запуска любых рабочих процессов или AR, которые необходимы.

Ответ 2

В нашем приложении MVC CQRS мы первоначально начали хранить всю информацию, относящуюся к пользователю, в домене, и, как и кто-то упоминал, существовал RegisterUserCommand и UserRegisteredEvent. После сохранения пользовательской информации в домене это событие было опубликовано и поднято на стороне чтения, которое также создало пользователя и сгенерировало все хэши паролей и т.д. Затем мы выполнили аутентификацию на стороне чтения: контроллер выполнил бы обратиться к "проверке подлинности службы проверки подлинности" для проверки подлинности.

Позже по дороге мы закончили полностью рефакторинг. Оказалось, что нам нужен доступ к информации, относящейся к пользователю, для создания безопасности для авторизации наших команд, которые мы выполнили на стороне обработки команд (наше приложение представляет собой распределенное приложение, которое отправляет асинхронные команды "огонь и забыть" в очередь, с автономный слушатель с другой стороны). Компонент безопасности затем нуждался в ссылке на наш домен, чтобы перейти и получить профиль пользователя, что привело к громоздким проблемам со ссылками.

Мы решили поместить материал безопасности пользователя в отдельную базу данных, которую мы считаем более центральным компонентом, а не принадлежим к домену или модели чтения. Мы по-прежнему сохраняем информацию о профиле пользователя в домене и читаем модели (например, название должности, URL-адрес учетной записи Twitter и т.д.), Но все связанные с безопасностью вещи, такие как хэши паролей, хранятся в этой центральной базе данных. Затем он доступен с помощью службы, доступной как для MVC, так и для авторизатора команд.

На самом деле нам не нужно было ничего менять в пользовательском интерфейсе для этого рефактора, так как мы просто вызвали службу для регистрации пользователей из обработчика пользовательских команд регистра. Если вы собираетесь это сделать, вам нужно быть осторожным здесь, чтобы сделать свои действия, связанные с обслуживанием пользователей, идемпотентными. Это означает, что вы можете дать вашим командам возможность повторного использования без побочных эффектов, поскольку вы обновляете 2 источника информации (ES и пользовательскую базу данных).

Наконец, вы могли бы, конечно, использовать поставщиков членства для этого центрального компонента, но с этим может быть ловушки. Мы закончили тем, что просто писали наши собственные - это довольно просто сделать. Эта статья ссылается на this, которая служит хорошим примером того, как ее реализовать.

Ответ 3

Вам следует подумать о создании отдельных объектов, таких как: посетитель (только что посетивший ваш сайт), пользователь (зарегистрированный), клиент (купил что-то) и т.д. Попытайтесь разбить вашу систему таким образом, даже если это вызывает немного данных избыточность. Дисковое пространство не является проблемой, но способность изменять различные компоненты системы независимо, как правило, очень важна.

Люди создают денормализованные таблицы аутентификации только для масштабирования, и только если ваша сторона чтения чтения является узким местом производительности. Если нет - обычная 3-я нормальная форма - это способ пойти.

В сценарии SimpleMembership все таблицы, созданные SimpleMembership, можно рассматривать как снимок "совокупности пользователей". И да, они будут дублировать некоторые данные в вашем хранилище событий. У вас могут быть такие события, как: UserCreated, UserUpdated, UserAssignedToRole и т.д.

И не обманывайте имя этого поставщика членства. Это не так просто и обычно имеет много вещей, которые вы можете легко жить без (зависит от вашего домена). Итак, возможно, вы можете использовать что-то вроде этого: https://gist.github.com/Kayli/fe73769f19fdff40c3a7