12

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

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

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

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

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

+0

Точно так же вы делаете это в системах на основе сообщений, AFAIK. Кажется, вы смешиваете авторизацию и аутентификацию. Что вы пытаетесь обеспечить? –

+0

Я не смешиваю их, я спрашиваю об обоих, на самом деле :) Кажется, моя главная проблема заключается в том, что я не знаю, как это делается в системах на основе сообщений;) – tuxbear

ответ

9

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

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

+2

+1 Во-вторых, это ... не все CQRS или ничего .. выберите и выберите, где это имеет смысл. для нас мы аутентифицируем пользователя и выдаем токен, который затем можем назначить заголовку каждой команды, чтобы обеспечить пользователю правильные уровни доступа и учетные данные для выполнения определенных операций в контексте команды. – Sarmaad

+2

Спасибо! Я думаю, что на самом деле это тот ответ, который я ищу. Я думал об этом решении, но, похоже, грязно иметь некоторые данные в хранилище событий и некоторые данные в db-таблицах. Я также обеспокоен возможностью воспроизведения события для восстановления состояния, поскольку это преимущество EventSouring является единственной причиной, по которой я его изучаю. Это также касается меня, что есть некоторые когнитивные накладные расходы, связанные с наличием двух архитектур друг за другом. – tuxbear

0

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

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

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

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

9

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

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

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

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

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

+0

Спасибо! Я бы тоже пошел по этому пути, чтобы получить советы от людей с реальным опытом использования этих конструкций. Мой большой поворот с помощью ES - это возможность создавать новые функции со старой информацией. Хранить ли данные домена как важные для вас события? – tuxbear

+1

Да, потому что это означает, что вы можете восстановить материал безопасности, переиграв ES. – jacderida

+0

Что вы описываете, просто используйте еще одну [проекцию] (http://abdullin.com/event-sourcing/projections.html) для обработки событий вашего домена. Это действительно очень просто, спасибо! Поэтому использование данных в реальном времени или устаревших данных зависит только от того, когда вы синхронизируете свою модель чтения с вашими событиями, не более того ... – inf3rno

 Смежные вопросы

  • Нет связанных вопросов^_^