CQRS 应用安全性等横切问题

发布于 2024-12-28 18:20:57 字数 506 浏览 3 评论 0原文

假设我有一个复杂的系统,其中有很多人。简单的想法就是员工/经理的关系,许多员工向一位经理汇报。现在,除了经理之外,还有能够代表经理行事的支持人员,可以操纵经理的员工。

在 CQRS 系统中,如何为“编辑员工”的假设操作建模消息,其中操作的调用者是支持人员。仅当工作人员根据经理安全关系对其领域内的员工采取行动时,该操作才能成功。

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

这个查询会发生在哪里?在发出“编辑员工”消息之前?

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

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

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

Suppose I have a complex system where there large trees of people. Simple thoughts are employees / manager relationship, many employees report to one manager. Now in addition to manager there are support staff that are capable of acting on the behalf of the manager can manipulate the managers' employees.

In a CQRS system how would you model a message for a hypothetical action of "edit employee" where the invoker of the action is a support staff. The action can only succeed if the staff member as per the manager security relationship is acting upon an employee in their realm.

Verifying the security of this would involve querying the database to validate that the person being modified is indeed inside the employee chain of that manager.

Where would this query occur? Prior to originating the "edit employee" message?

If the data is upfront validated before originating the message, in an eventually consistent system suppose that before the "edit employee" message has been processed a separate action has occurred that would have removed the authority of the user to complete the "edit employee" action. If the the command handler doesn't validate the security concerns of that message, the message would still succeed even though the user no longer the authority to execute it.

This would seem to imply that double sided validation, similar to UI validation & server side validation would be the best course of action. However the method of completing that validation seems as though it would violate key tenets to CQRS.

What approach(es) are best when having to deal with these and other similar cross cutting concerns when using CQRS?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清醇 2025-01-04 18:20:58

首先,我同意@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,即员工。

员工域

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

因此,我将在我的控制器和域中应用相同的安全检查。我可能会将其作为封装方法(好吧,可能是我将传递到存储库的封装标准类)。

所以我希望这对我如何处理这种情况有所帮助。如果有问题请告诉我,我将详细回答。

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

First, I agree with @Yahia's comment that there isn't a general answer. With that said, here's how I'd approach it.

To begin with, I would probably go with the double validation -- once in my controller when the request was first received, and then later in my domain as it's processing the command. Some may not agree with that, but I would rather prevent a command from being issued and letting the user know immediately that they were not authorized to perform some action rather than having the command go through and rely on eventual consistency for some error notice to alert the user after the fact that they could not perform the action.

So, in terms of pseudo-code, here's my approach to Edit Employee:

Controller

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

So here my command service picks up the command and routes it to the appropriate AR in my domain, which would be Employee.

Employee Domain

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

So I would apply the same security check in both my controller and in my domain. I would have this, probably, as an encapsulated method (well, probably an encapsulated criteria class that I would pass to the repository).

So I hope this helps out with how I would approach this scenario. Let me know if there are questions and I'll elaborate in my answer.

I hope this helps. Good luck!

神仙妹妹 2025-01-04 18:20:58

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

I'd probably skip CQRS entirely for this domain and have the web tier talk directly to the DB tier (no messaging). Simple optimistic concurrency should handle the few conflicts that would happen.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文