Chr*_*sic 5 security messaging cross-cutting-concerns domain-model cqrs
假设我有一个复杂的系统,那里有大量的树木.简单的想法是员工/经理关系,许多员工向一位经理报告.现在除了经理之外,还有能够代表经理行事的支持人员可以操纵经理的员工.
在CQRS系统中,您如何为"编辑员工"的假设操作建模消息,其中操作的调用者是支持人员.只有当经理安全关系中的工作人员对其领域的员工采取行动时,该行动才能成功.
验证此安全性将涉及查询数据库以验证被修改的人确实在该经理的员工链内.
这个查询会在哪里发生?在发起"编辑员工"消息之前?
如果在发起消息之前对数据进行了前期验证,则在最终一致的系统中,假设在处理"编辑员工"消息之前,已发生单独的操作,该操作将删除用户完成"编辑员工"操作的权限.如果命令处理程序未验证该消息的安全性问题,则即使用户不再具有执行该消息的权限,该消息仍将成功.
这似乎意味着双边验证,类似于UI验证和服务器端验证将是最佳的行动方案.然而,完成该验证的方法似乎违反了CQRS的关键原则.
在使用CQRS时,必须处理这些和其他类似的横切问题时,哪种方法最好?
首先,我同意@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");
}
Run Code Online (Sandbox Code Playgroud)
所以这里我的命令服务选择命令并将其路由到我的域中的相应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));
}
}
Run Code Online (Sandbox Code Playgroud)
所以我会在我的控制器和我的域中应用相同的安全检查.我可能会把它作为一个封装的方法(好吧,可能是我将传递给存储库的封装标准类).
所以我希望这有助于我如何处理这种情况.如果有问题请告诉我,我会在答案中详细说明.
我希望这有帮助.祝好运!