具有动态角色的基于角色的访问控制

2024-01-14

我们有一个应该实现 rbac 的 Nest 应用程序。我根据守卫文档为其添加了一个基本的守卫和装饰器:https://docs.nestjs.com/guards https://docs.nestjs.com/guards。 问题:这仅允许静态角色。

我们的目标:就我们而言,我们有一个Contract实体。仅当合同承包商 (<User>)或承包商的主管(<User>)尝试访问它。 我不想实施类似的事情if (contract.contractor.id === user.id)等等,因为我们有很多不同的案例,随着时间的推移,这会让事情变得一团糟。

它看起来像下面这样:

@Get()
@Roles(ROLES.ADMIN, ROLES.CONTRACTOR, ROLES.SUPERVISOR)
getContractById(...): Contract {
    return this.contractService.findById(...);
}

当然,ROLES.SUPERVISOR只是一个字符串,然后与用户的静态角色进行匹配。所以问题是:如何使用动态角色来实现类似的功能,例如主管角色,它仅在某些项目的上下文中是动态的。


您需要首先从概念上解决这个问题。

我认为您应该编写一个能够计算特定合约的特定用户是什么的方法。

超级简单的例子:

getUserRoleForContract(user: User, contract: Contract): ROLES {
    // your logic goes here
    if (contract.contractor.id === user.id) {
         return ROLES.CONTRACTOR;
    } else if (...) {...}

    return null;
}

在你的守卫中,从上下文中,你知道哪个用户和合约请求是关于哪个用户和合约请求,利用此方法获取 ROLE,然后将结果与请求的角色进行比较。

现在,您明确表示您不想使用这种方法(检查用户和合同的每个组合)。

我认为你应该改进这一点getUserRoleForContract现在,基于您对实体关系的了解,实施方法。

从你的问题中,我看到承包商和主管。此拟合基于该(有限)信息:

getUserRoleForContract(user: User, contract: Contract): ROLES {
    const allAvailableRoles = [ROLES.CONTRACTOR, ROLES.SUPERVISOR];

    for (let role of allAvailableRoles) {
        if (contract[role.toLowerCase()].id === user.id) {
            return role;
    }

    return null;
}

这将在假设合约上的每个用户关系实际上是 ManyToOne 且名称与 ROLE 名称相同但小写的情况下起作用(并且假设 ROLES 枚举值是相同的大写字符串)。

总而言之,我希望这对您有所帮助并回答问题。

EDIT2:我修复了 this 指向的 URL。

我刚刚把答案放在这里:为 Nestjs 创建 isAuthor 防护的最佳方法是什么? https://stackoverflow.com/questions/72917725/what-would-be-the-best-way-to-create-an-isauthor-guard-for-nestjs/73885562#73885562。它涵盖了 Nest.js 中 RBAC 的更大解决方案(包括此场景)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有动态角色的基于角色的访问控制 的相关文章