出于授权原因,CQR和交叉切割问题等问题

发布于 2025-01-23 20:50:19 字数 2176 浏览 0 评论 0原文

让我们假设一个单片网络服务。建筑设计基于DDD,并将域分为子域。这些是根据CQRS模式结构的。如果请求通过演示层到达,则在这种情况下是一个安息的接口,控制器会生成相应的命令,并通过命令总线执行。

到目前为止,一切都很好。现在的问题是某些命令只能由某些用户执行,因此必须进行访问控制。在三层体系结构中,可以使用ABAC相对轻松地求解。但是,为了能够使用ABAC,必须加载和已知域资源。身份验证由演示层的各个技术接管,并在请求中存储身份验证的用户。例如,使用Passport.js用于RESTFUL界面的JWT承载令牌。

方法#1:作为命令处理程序的一部分访问控制

​是将访问控制转移到基于ABAC的命令处理程序中。如果成功执行,它将不像往常一样返回,如果访问被剥夺了例外。

// change-last-name.handler.ts

async execute(command: ChangeUserLastNameCommand): Promise<void> {
  const user = await this._userRepository.findByUsername(command.username);

  if (!user) {
    throw new DataNotFoundException('Resource not found');
  }

  const authenticatedUser = null; // Get authenticated user from somewhere

  // Handle ABAC
  if(authenticatedUser.username !== user.username) {
      throw new Error();
  }

  user.changeLastName(command.lastName);
  await this._userRepository.save(user);
  user.commit();
}

但是,这种方法对我来说似乎很不洁。 问题:在我看来,访问控制不应该是单个命令处理程序的责任,应该吗?尤其是因为很难在此级别上获取经过身份验证的用户或包含经过身份验证的用户的请求。命令处理程序应适用于演示层的所有可能技术(例如GRPC,RESTFUL,WEBSOCKETS等)。

方法2:作为演示层的一部分访问控制或使用AOP

对我来说是干净的方法是从处理程序中访问访问控件并在执行命令之前执行它。通过在演示层中手动调用它,例如,使用AccessControlService来实现业务安全规则,或使用AOP进行非侵入性编程,从而可以使用> code> AccessControlservice

这里的问题在于,演示层没有骨料的任何属性。对于ABAC,首先必须使用查询总线加载骨料。然后可以在演示层中进行ABAC,例如在Restful Controller中。

这对我来说基本上是一个很好的方法。访问控件是演示层的责任,或者在必要时,方面(AOP)和业务逻辑(域 + CQR)被解耦。 问题:这里的主要问题是,从数据库的角度出现了冗余。对于ABAC,必须通过查询预加载聚合,以便能够确定是否可以执行命令。如果允许执行命令,则可能会再次从数据库中加载完全相同的汇总,这次只是为了进行更改,即使汇总已经加载了不久。

问题:是否有任何改进的建议或建议?我试图找到文献中正在寻找的内容,这不是很有帮助。我遇到了以下“ nofollow noreferrer”>在域驱动的设计中,Michiel Uithol的安全性给出一个很好的概述,但没有回答我的问题。如何解决CQRS体系结构中的安全问题?还是冗余数据库访问可以忽略不计,我实际上已经有了解决方案?

Let's assume a monolithic web service. The architectural design is based on the DDD and divides the domain into sub-domains. These are structured according to the CQRS pattern. If a request arrives via the presentation layer, in this case a RESTful interface, the controller generates a corresponding command and executes it via the command bus.

So far so good. The problem now is that certain commands may only be executed by certain users, so access control must take place. In a three-layer architecture, this can be solved relatively easily using ABAC. However, to be able to use ABAC, the domain resource must be loaded and known. The authentication is taken over by the respective technology of the presentation layer and the authenticated user is stored in the request. For example, JWT Bearer Tokens using Passport.js for the RESTful interface.

Approach #1: Access Control as part of the command handler

Command Handler + ABAC

Since the command handler has access to the repository and the aggregate has to be loaded from the database anyway in order to execute the command, my first approach was to transfer access control to the command handler based on ABAC. In case of a successful execution it returns nothing as usual, if access is denied an exception is thrown.

// change-last-name.handler.ts

async execute(command: ChangeUserLastNameCommand): Promise<void> {
  const user = await this._userRepository.findByUsername(command.username);

  if (!user) {
    throw new DataNotFoundException('Resource not found');
  }

  const authenticatedUser = null; // Get authenticated user from somewhere

  // Handle ABAC
  if(authenticatedUser.username !== user.username) {
      throw new Error();
  }

  user.changeLastName(command.lastName);
  await this._userRepository.save(user);
  user.commit();
}

However, this approach seems very unclean to me. Problem: In my opinion, access control shouldn't be the responsibility of a single command handler, should it? Especially since it is difficult to get the authenticated user or the request, containing the authenticated user, at this level. The command handler should work for all possible technologies of the presentation layer (e.g. gRPC, RESTful, WebSockets, etc.).

Approach #2: Access control as part of the presentation layer or using AOP

A clean approach for me is to take the access control from the handler and carry it out before executing the command. Either by calling it up manually in the presentation layer, for example by using an AccessControlService which implements the business security rules, or by non-invasive programming using AOP, whereby the aspect could also use the AccessControlService.

The problem here is that the presentation layer does not have any attributes of the aggregate. For ABAC, the aggregate would first have to be loaded using the query bus. An ABAC could then be carried out in the presentation layer, for example in the RESTful controller.

Presentation Layer + ABAC

That's basically a good approach for me. The access control is the responsibility of the presentation layer, or if necessary an aspect (AOP), and the business logic (domain + CQRS) are decoupled. Problem: The main problem here is that redundancies can arise from the database point of view. For the ABAC, the aggregate must be preloaded via query in order to be able to decide whether the command may be executed. If the command is allowed to be executed, it can happen that it loads exactly the same aggregate from the database again, this time simply to make the change, even though the aggregate has already been loaded shortly before.

Question: Any suggestions or suggestions for improvement? I tried to find what I was looking for in the literature, which was not very informative. I came across the following Security in Domain-Driven Design by Michiel Uithol, which gives a good overview but did not answer my problems. How do I address security concerns in a CQRS architecture? Or are the redundant database access negligible and I actually already have the solution?

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

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

发布评论

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

评论(1

忱杏 2025-01-30 20:50:19

在到达命令处理程序之前,我将处理身份验证和总体授权,因为这是一个单独的问题。

与授权分开处理身份验证也很重要,因为存在单独的担忧。如果您同时处理身份验证和授权,它可能会变得非常凌乱。

然后,您将在处理程序中执行最终授权(例如),例如,如果您具有命令addProductTocart,那么我将确保最初创建Cart-Aggreagate的用户与制作AddAddProductTocart命令的用户相同。

I would handle authentication and the overall authorization in the infrastructure, before it reaches the command handlers, because it is a separate concern.

It is also important to handle authentication separately from authorization, because there are separate concerns. It can become pretty messy if you handle authentication and authorization at the same time.

Then you I would do final authorization in the handler (if needed), for example if you have a command AddProductToCart, then I would make sure that the user who initially created the cart-aggreagate is the same as the one making the AddProductToCart command.

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