5

假设我有一个复杂的系统,那里有大量的人。简单的想法是员工/经理的关系,许多员工向一位经理报告。现在,除了经理之外,还有能够代表经理操作管理人员的支持人员。CQRS应用横切关注,如安全

在CQRS系统中,如何为“编辑员工”的假设行为建立消息模型,其中行动的调用者是辅助人员。如果员工根据经理安全关系对他们的领域中的员工采取行动,该行动才能成功。

验证其安全性将涉及查询数据库以验证被修改的人是否确实在该经理的员工链内。

此查询会在何处发生?在发起“编辑员工”消息之前?

如果在发送消息之前预先验证数据,则在最终一致的系统中,假设在处理“编辑员工”消息之前发生了一个单独的操作,该操作已经取消了用户的权限以完成“编辑员工“操作。如果命令处理程序未验证该消息的安全性问题,则即使用户不再有权执行该消息,该消息仍然会成功。

这似乎意味着双面验证,类似于UI验证&服务器端验证将是最佳的行动方案。然而,完成验证的方法好像违反了CQRS的关键原则。

使用CQRS时,在处理这些和其他类似的横切问题时,哪种方法最好?

+1

IMO没有普遍的答案......我会一直在命令处理器端验证*至少*和**可选**“前期”(可能在接受消息进入队列的部分) – Yahia

+0

我还认为区分真正的横切关注点,如认证,简单授权(该用户是否允许执行此类操作)很重要,从业务规则管理是否允许特定实体的某些操作。 –

回答

3

我可能完全跳过CQRS的这个域,并让Web层直接与数据库层(无消息传递)对话。简单的乐观并发应该处理少数会发生的冲突。

+0

你能解释一下你的思考过程吗?为什么你的第一个陈述? –

+1

因为这是最简单的解决方案,所以可能可以工作:) –

+0

这绝对是真的,但是如果最简单的总是最好的行为方式,那么根本就不会存在CQRS模式? –

5

首先,我同意@ 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)); 
    } 
} 

所以我会采用同样的安全检查中我的两个控制器和我的域名。我想这可能是封装的方法(很可能是封装的标准类,我会传递到存储库)。

所以我希望这可以帮助我如何处理这种情况。让我知道是否有问题,我会在我的答案中详细说明。

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

+0

你为什么要在两个层面上应用它?域层不是所有应该通过的点,因此应该在那里处理诸如安全和验证等问题? – Juri