【问题标题】:RBAC - How to implement per instance access control? (DDD)RBAC - 如何实现每个实例的访问控制? (DDD)
【发布时间】:2016-04-27 17:00:44
【问题描述】:

在我用 javascript (Node.js) 编写的 DDD 应用程序中,我在授权通用子域的实现上遇到了困难。我检查了 RBAC / ACL 授权模型如何实现这一点,但它们似乎没有我需要的每个实例的权限。

据我了解,RBAC 具有基于角色的授权。用户被分配到角色。角色是分层的并继承权限。角色可以拥有多个权限。权限允许对资源执行命令。

但是,根据 RBAC 的定义,资源是通用的,如“帖子”、“评论”、“书”等。它们不是特定于实例的(如帖子(id:9283984))。例如,不可能在 RBAC 中定义只有创建帖子的用户才能编辑它。在给定的“帖子(id:2398493)”上将角色“管理员”分配给“用户(id:(8290321)”似乎是不可能的

定义有权执行修改其他人在特定资源上的角色的命令的角色变得更加复杂。

我的申请要求是:

发出CreateLedger 命令的User 被自动分配为此LedgerAdmin。他只能将其他人分配为他是@9​​87654328@ 的Ledgers 的ManagersCollaboratorsViewers。他也可以撤销这些角色。允许Managers 管理LedgerAccountsCollaborators 可以在这个Ledger 上编辑Transactions,而Viewers 只能查看数据(只读)。一个Admin 可以将Admin 角色分配给他是Admin 的另一本书User

我最初的想法是,为了让用户能够管理用户在资源上的角色,需要有一个映射

user(id:X) -> role(name:Z) -> permissions -> resource(id:Y) -> commands

但在 RBAC 中只能分配

user(id:X) -> role(name:Z) -> permissions -> resource(name:"Ledger") -> commands

然后,为了克服 RBAC 的这个限制,我想到了用它们的 id 来命名资源,比如

user(id:X) -> role(name:Z) -> permissions -> resource(name:"Ledger:39823847") -> commands

但这似乎是错误的。我还没有看到任何使用资源名称作为实际实例映射的 RBAC 示例。

我用错了锤子?我看错了吗?是否有其他更适合此任务的访问控制模型?或者这是要走的路?如果有人能指出我正确的方向,我将不胜感激。

感谢您的帮助

【问题讨论】:

    标签: authorization domain-driven-design access-control rbac


    【解决方案1】:

    作为通用子域的授权

    如果您想将授权建模为通用子域,那么您确实使用了错误的锤子。看看claims-based authorization。使用声明,您可以定义类似modify-post:2937472 的声明。或者,您当然可以进一步抽象化这些信息。

    通过这种方法,通用授权子域提供了一个“容器”,其他子域在其中存储关联。因此,这种方法需要仔细整合子域,以便将事物保留在它们所属的位置。

    授权为支持子域

    注意:如果您通过仔细分析和设计得出的结论是授权需要是一个通用的子域,那么以下内容不是您想要的。无论如何,我将其添加到我的答案中,因为对于不需要单独授权子域的项目来说,它可能是一个可行的解决方案。所以它来了:

    一种根本不同的方法是将授权设计为依赖于核心子域的支持子域。有了这个,您可以使用核心模型来定义访问权限,这使得它更简单,更容易理解。

    例如,博客系统的授权机制可以使用核心域中的作者、帖子、版主等概念。如果您有复杂的授权要求,这是一个巨大的胜利。

    与通用子域方法相比,明显的权衡是授权不会是通用的,而是与特定子域相关联。这对于特定项目可能可以接受,也可能不可接受,但对于不需要单独的、可重用的授权机制的小型系统来说,这是一种实用的方法。

    【讨论】:

    • 您能否进一步扩展授权作为支持子域。我不太确定使用核心模型定义访问权限是什么意思。如果您将子域视为支持域,那似乎倒退了。其他子域应该使用支持的子域来定义访问权限吗?同样使用基于声明的授权,是否所有声明都必须存在于内存中才能进行验证?如果是这样,您如何只加载与操作相关的声明?您无法加载整个 ACL。
    • @plalx:在这种情况下,支持的子域不支持核心域,而是应用程序本身。我猜有些人会争辩说,在这种情况下,授权不是一个单独的子域,而是核心域的一部分。
    • @plalx:请注意,如果您想构建可重用的授权机制,这不是一个好的解决方案,如果您将授权设计为通用子域,通常会出现这种情况。所以这有点反对这里的问题。我只是想提一下,因为它是具有“隔离”授权机制的应用程序的简单解决方案。我会更新我的答案,以便清楚。
    • @theDmi 混合解决方案是否可取?通过实现一个通用授权子域,然后可以由支持 LedgerAuthorization 子域使用? LedgerAuthorization 子域将负责通用身份验证子域和 Ledger 域之间的映射?
    • @Ludo 您是否认为仅映射就足够复杂,需要一个独立的子域?如果是,那么这确实是一个解决方案。
    猜你喜欢
    • 2017-05-25
    • 1970-01-01
    • 2021-06-13
    • 2014-01-10
    • 2017-03-09
    • 1970-01-01
    • 2018-01-07
    • 2016-10-25
    • 2012-02-14
    相关资源
    最近更新 更多