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");
}

因此,在这里,我的命令服务接收命令并将其路由到我的域中的适当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));
  }
}

所以我会在我的控制器和域中应用相同的安全检查。我可能会把它作为一个封装的方法(好吧,可能是一个封装好的标准类,我会把它传递给存储库)。

所以我希望这有助于我如何处理这种情况。如果有问题请告诉我,我会在回答中详细说明。

我希望这能有所帮助。祝你好运

对于这个域,我可能会完全跳过CQRS,让web层直接与DB层对话(没有消息)。简单的乐观并发应该处理可能发生的少数冲突。

相关内容

  • 没有找到相关文章

最新更新