DynamoDB中具有用户和用户组的权限模型

时间:2019-06-28 13:06:47

标签: amazon-dynamodb

我有一个“关系”模型,具有以下类型:

  • 用户
  • 用户组
  • 物品

用户可以属于多个组,并且组可以具有多个用户。

项目具有允许其读取或执行操作的用户和组。

最常见的查询是,用户通过其ID查询项目。为此,必须检查用户是否具有查询项目所需的权限。换句话说,它或其一个组必须对该项目具有权限。

到目前为止我想出了什么

一种解决方案是,这些商品具有以下属性:

  • 用户

    • 主键:用户ID
    • 没有排序键
    • 属性:组列表
  • 项目:

    • 主键:item-id
    • 排序键:
      • 'data':此项的数据
      • <user/group-id>:对此用户或组的权限

因此要检查权限,必须要

  • 获取用户组
  • 通过使用用户ID和所有组ID作为排序键查询item-id(使用BatchGetItems)来获取权限。
  • 检查用户或其任何组是否具有所需的权限。

问题

我觉得这可能会导致大量查询,尤其是在组数很高的情况下。

是否有一种无需昂贵的权限检查即可实现此权限模型(或类似权限模型)的方法?

1 个答案:

答案 0 :(得分:0)

简短答案-将权限与数据分开。

详细答案-您应该使用轻量级权限表来存储组与用户和项目之间的关系。您不应该在项目上使用任何与权限相关的排序键,并且除非有特殊原因允许使用具有相同ID的项目(例如存储项目的版本历史记录),否则您可能根本不应该使用任何排序键为您的物品。

权限表具有两个属性,我将其称为entity(哈希键)和relationship(排序键)。 (不过,您可以使用所需的任何名称。)该表还具有GSI,其中relationship是哈希键,而entity是排序键。因为此表的行很小,所以查询非常便宜。您可能读取超过100行,并且仅消耗1个RCU。

entity属性只是一个userId或groupId。 relationship属性是关系类型和另一个ID的组合。 (您可以将任何所需的ID用于ID,但我将在所有示例中使用数字。)

以下是一些示例数据:

entity      | relationship
===========================================
user-0001   | member-of:group-1000
user-0001   | member-of:group-3000
user-0002   | can-access:item-1111
user-0002   | member-of:group-2000
group-1000  | can-access:item-1111
group-2000  | can-access:item-2222

要确定用户是否有权访问给定项目,您需要两个查询。在权限表中查询userId,并在GSI中查询“可以访问” itemId关系。然后,比较两个查询结果以查看是否有共同的组(或者用户是否有权直接访问该项目)。

例如,如果您想查看user-0001是否可以访问item-1111,则可以查询user-0001并返回[member-of:group-1000, member-of:group-3000]。然后,您将在GSI中查询can-access:item-1111,然后返回[user-0002, group-1000]。比较这两个结果,您会发现user-0001可以通过item-1111来访问group-1000

此模型的另一个好处是它足够灵活,可以处理其他权限用例。以下是该数据的外观示例:

entity      | relationship
===========================================
user-0001   | admin-of:group-1000
user-0001   | member-of:group-1000
user-0002   | member-of:group-2000
user-0002   | owner-of:item-1111
group-1000  | can-write:item-1111
group-1000  | can-read:item-1111
group-2000  | can-read:item-1111

在此示例中,我们还有一些用户可以管理组,我们已经分离了项目的读写权限,并且可以将用户或组定义为项目的所有者(这可能意味着他们可以修改谁有权读取或写入该项目。


一个警告是,这假定组不能嵌套。如果可以嵌套组,那么您将需要更多查询来遍历嵌套组的层次结构,使用AWS Neptune或其他数据库来存储权限可能会更好。