CQRS, применяющий сквозные аспекты, такие как безопасность

Предположим, у меня есть сложная система, где есть большие деревья людей. Простые мысли - это отношения сотрудников и менеджеров, многие сотрудники подчиняются одному менеджеру. Теперь помимо менеджера есть вспомогательный персонал, который способен действовать от имени менеджера и может манипулировать сотрудниками менеджера.

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

Проверка безопасности этого потребует запроса к базе данных, чтобы убедиться, что изменяемый человек действительно находится в цепочке сотрудников этого менеджера.

Где может возникнуть этот запрос? До создания сообщения «изменить сотрудника»?

Если данные предварительно проверяются перед отправкой сообщения, в конечном итоге согласованной системе предположим, что до того, как сообщение «изменить сотрудника» было обработано, произошло отдельное действие, которое лишило бы пользователя права выполнять действие «изменить сотрудника». . Если обработчик команды не подтверждает проблемы безопасности этого сообщения, сообщение все равно будет успешным, даже если пользователь больше не имеет полномочий для его выполнения.

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

Какие подходы лучше всего подходят для решения этих и других подобных комплексных проблем при использовании CQRS?


person Chris Marisic    schedule 25.01.2012    source источник
comment
IMO, общего ответа нет... Я всегда проверял бы на стороне обработчика команд по крайней мере и необязательно заранее (что может быть в той части, которая принимает сообщение в очередь)   -  person Yahia    schedule 26.01.2012
comment
Я также думаю, что важно различать настоящие сквозные проблемы, такие как аутентификация, простая авторизация (разрешено ли этому пользователю выполнять действие этого типа) и бизнес-правила, которые определяют, разрешено ли что-либо для конкретного объекта.   -  person Udi Dahan    schedule 24.10.2015


Ответы (2)


Я бы, вероятно, полностью пропустил CQRS для этого домена и связал бы веб-уровень напрямую с уровнем БД (без обмена сообщениями). Простой оптимистичный параллелизм должен справляться с несколькими конфликтами, которые могут произойти.

person Udi Dahan    schedule 26.01.2012
comment
Можете ли вы объяснить свой мыслительный процесс относительно того, почему ваше первое утверждение? - person Chris Marisic; 26.01.2012
comment
Потому что это самое простое решение, которое могло бы сработать :) - person Udi Dahan; 26.01.2012
comment
Это, безусловно, верно, однако, если бы самый простой всегда был лучшим способом действий, шаблона CQRS вообще не существовало бы? - person Chris Marisic; 26.01.2012
comment
@ChrisMarisic простота и наивность — не одно и то же. Возможность работать с моделью чистого чтения без необходимости разбираться в сложностях сложной бизнес-модели может быть очень простой по сравнению с альтернативой. Также может быть проще иметь возможность моделировать бизнес-поведение, не выясняя, какие из методов получения объекта действительно необходимы для обеспечения соблюдения бизнес-правил, а какие существуют только для одного из многих представлений. Вообще говоря, смешивание чтения и записи может ( и часто приводит) приводит к нематериальному беспорядку, который очень далек от простого. - person Dennis Traub; 27.01.2012
comment
@DennisTraub Я не совсем уверен, какие моменты вы пытались донести там, можете ли вы перефразировать некоторые из своих комментариев? - person Chris Marisic; 27.01.2012
comment
@ChrisMarisic Я пытаюсь сказать, что такие шаблоны, как CQRS, могут помочь упростить сложные системы. - person Dennis Traub; 27.01.2012
comment
+1 за заявление Уди. Просто запросите БД, чтобы определить, разрешено ли конкретное действие. В зависимости от сложности ваших деревьев сотрудников у Джо Селко есть отличная книга по работе с деревьями в SQL: Trees and Hierarchies in SQL. - person Jonathan Oliver; 29.01.2012

Во-первых, я согласен с комментарием @Yahia о том, что общего ответа нет. С учетом сказанного, вот как я бы к этому подошел.

Для начала я бы, вероятно, использовал двойную проверку — один раз в моем контроллере, когда запрос был впервые получен, а затем в моем домене, когда он обрабатывает команду. Некоторые могут не согласиться с этим, но я бы предпочел предотвратить ввод команды и немедленно сообщить пользователю, что он не уполномочен выполнять какое-либо действие, а не выполнять команду и полагаться на возможную согласованность для предупреждения об ошибке. пользователя после того, как он не смог выполнить действие.

Итак, с точки зрения псевдокода, вот мой подход к редактированию сотрудника:

Контроллер

[HttpPost]
ActionResult Edit(Employee emp){

  //get employee org information from _employeeRepository
  //validate if _loggedInUserID is able to edit emp.ID

  if(isValid) {
    //construct command
    _commandService.EnqueueCommand(new EditEmployee(emp.ID, emp.Name, emp.Salary));
  } else {
    return View("PermissionError");
  }

  return Redirect("EmployeeProperties");
}

Итак, здесь моя командная служба принимает команду и направляет ее соответствующему AR в моем домене, которым будет Employee.

Домен сотрудника

protected void EditEmployee(userID, employeeID, employeeName, salary){
  //get employee org information from _employeeRepository
  //validate if userID is able to edit employeeID

  if(isValid) {
    //apply event
    ApplyEvent(new EmployeeEdited(userID, employeeID, employeeName, salary));
  }
}

Поэтому я бы применил одну и ту же проверку безопасности как к своему контроллеру, так и к своему домену. Мне бы это, наверное, как инкапсулированный метод (ну, наверное, инкапсулированный класс критериев, который я бы передал в репозиторий).

Поэтому я надеюсь, что это поможет мне понять, как я подхожу к этому сценарию. Дайте мне знать, если есть вопросы, и я уточню в своем ответе.

Надеюсь, это поможет. Удачи!

person David Hoerster    schedule 26.01.2012
comment
Почему вы применяете его на обоих уровнях? Разве доменный уровень не является точкой, через которую все должно проходить, и, следовательно, там должны решаться такие вопросы, как безопасность и проверка? - person Juri; 10.03.2015