【问题标题】:Authorization of commands in AxonAxon 中的命令授权
【发布时间】:2020-08-02 19:00:22
【问题描述】:

到目前为止,我一直在 CommandHandlers 中处理授权。

一个例子是我有一个包含经理列表的聚合“团队”(来自用户的 AggregateIdentifier)。团队聚合中的所有命令处理程序然后验证执行命令的用户是团队的经理。 userId 作为元数据注入到基于 SecurityContext 的 CommandHandlerInterceptor 中。

我主要担心的是,当我使用 sagas 时,跨针对不同聚合发出的命令维护用户上下文会成为额外的开销。除此之外,管理器关联可能会在 saga 运行期间以及随后的失败命令期间过期,从而导致状态不完整,也需要使用一些回滚功能来处理。

最好在我的控制器层中进行授权以避免额外的开销,还是我应该将它视为更好的做法,让我的 CommandHandlers 决定命令是否对聚合有效?

【问题讨论】:

    标签: event-sourcing axon


    【解决方案1】:

    我认为执行某些操作/命令的授权不是特定于域的逻辑。相反,它更像是您在整个应用程序中需要的一种横切关注点。因此,将它放入 @CommandHandler 注释方法在我的脑海中并不是理想的位置。但是,将其放在附近很有意义。

    您已经指出您已经在使用 CommandHandlerInterceptor 来填充 Spring SecurityContext,因此我假设您正在使用 CommandDispatchInterceptor 来填充命令的 MetaData 以及发送命令时的信息。这确实是拦截器逻辑的一个很好的用途,所以我会保留它。然而,这是一组信息,它不会验证它。

    为此,您可以构建自己的Handler Enhancer,用于验证命令的安全元数据。您甚至可以构建一个专用的注释,然后添加到 @CommandHandler 注释旁边,该注释描述了所需的角色。这样,该方法仍然描绘了给定命令所需的角色,但实际验证可以在这个 Handler Enhancer 中为您完成。

    现在,让我们回到你的问题:

    最好在我的控制器层进行授权以避免额外的开销,还是我应该将它视为更好的做法,让我的 CommandHandlers 决定命令是否对聚合有效?

    我认为总体上这样做很好,通过使用处理程序增强器可能会使其更清洁。当谈到您对 Saga 的关注时,我认为您应该分开看待。 Saga 处理事件,事实 发生了某事。忽略这一事实,因为发起导致这一事实的操作的人没有权利并不能解决它仍然发生的问题。补充一下,您确实根本无法保证 Saga 的时间安排。也许您的 Saga 涉及历史事件,这意味着它完全超出了范围。

    如果可能在您的系统中,我会将 Saga 想要发布的 任何 命令视为由“系统用户”发送。 Saga 不是您的用户(具有特定角色)会直接影响的东西;这都是间接的。 Saga 在您的系统内部,因此它是描述执行操作意图的系统。

    这是我的两分钱,希望这可以帮助你@Vincent!

    【讨论】:

    • 谢谢,这确实有助于获得第二意见。我更新了我的 CommandHandlerInterceptor 以检查 RequestContextHolder.getRequestAttributes() 是否不为空。如果是这样,它将从安全上下文中提取用户 ID 和角色,并将元数据字段“内部”设置为 FALSE。如果它为空,那么我假设它是一个内部服务调用,只需将元数据字段“内部”设置为 TRUE。 Example 我添加了一个 HandlerEnhancer,在 WrappedMessageHandlingMember 中,canHandle 方法正在检查这个“内部”标志。
    • 很高兴听到@Vincent!很高兴能得到帮助:-)
    • 一个后续问题。我通过简单验证用户在安全上下文中具有适当的角色来运行它,但是我有另一个场景,我希望使用 HandlerDefinition 中的存储库提取我的“团队”聚合。为了解决这个问题,我正在考虑自动连接存储库,但它看起来很笨重,除了将它作为我的“WrappedMessageHandlingMember”扩展的构造函数的参数之外,我无法找到一个好方法,以便在“canHandle”方法
    • 这是Team 聚合实际命令的聚合吗?或者,这是您需要验证状态的不同聚合吗?
    • 我可以看到我描述了我的后续问题有点糟糕,对此感到抱歉:) 我有一个 Team 聚合命令要去的地方。我也有一个Event 聚合。 TeamEvent 聚合都包含 List<ProfileId> managers;如果用户出现在任一管理器列表中,则允许他们执行该命令。它们基于TeamId 彼此“相关”聚合标识符是 UUID 和 EventId 的组合(Event 的聚合标识符)目标是获取 Team 聚合和 Event 聚合并检查两者的经理名单。
    猜你喜欢
    • 2014-01-15
    • 2019-09-25
    • 2021-09-07
    • 2019-05-30
    • 2013-06-14
    • 2018-06-24
    • 1970-01-01
    • 1970-01-01
    • 2021-03-23
    相关资源
    最近更新 更多