为 RESTful 设计资源权限优先级
Designing resource permission priority for RESTful
这与有权在资源端点上发出 GET/POST/PUT/DELETE 请求无关。这是关于某些用户对某些资源具有 GET/POST/PUT/DELETE 请求权限。
在我们的应用程序中,我们使用以下 sqlalchemy 架构将其称为访问控制列表 (ACL)
class ACL(db.Model):
__tablename__ = 'acl'
id = db.Column(db.Integer, primary_key=True)
res_id = db.Column(db.Integer, nullable=True)
res_type = db.Column(db.String(50), nullable=True)
permission = db.Column(db.String(20), nullable=True)
is_allowed = db.Column(db.Boolean, default=True)
users = db.relationship("User", secondary=acl_users)
created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow)
此ACL 与用户具有多对多关系,与每个资源具有多对一关系。这个 ACL 可以是四个东西:
- 如果res_id不为空且用户不是空列表,则称为"Exact",因为它指定了特定用户对特定资源的权限
- 如果res_id为空且用户不是空列表,则称为"Anything",因为它指定了特定用户对任何资源的权限
- 如果res_id不为空且用户为空列表,则称为"Anyone",因为它指定了任何用户对特定资源的权限
- 如果res_id为null且users为空列表,则称为"Any",因为它指定了任何用户对任何资源的权限
我不确定这种设计是否普遍,但它似乎拥有定义资源权限所需的一切。
问题如下:
如果一个资源有多个ACL,优先级应该是多少?
我们只有三个选择:
- 在 ACL table 上添加 'priority' 列并让它确定优先级。这种方法是有道理的,但是创建按优先级考虑 ACL 的 Fetch Collection 查询会变成一场噩梦。
- 错误 >> 正确。例如"Anyone" 错误胜过 "Exact" 正确。如果 "Anyone" 设置为 False,则没有用户对该资源具有权限。这最容易进行 Fetch Collection 查询。
- 确切 >> 任何人 >> 任何人 >> 任何人。即使 "Anyone" 为 False,如果 Exact user 设置为 True,则除该用户以外的所有人都具有权限。进行 Fetch Collection 查询既不容易也不不可能。
这三个选项中的哪一个最能反映许可的常见做法?
我不知道这些是否常见,总体上的模式与我过去看到的权限设置方式略有不同。 (顺便说一句,我在查找其他人如何对我自己的问题进行权限处理时发现了这个post,所以感谢您的不同观点!)
我以前的系统遵循非常标准的角色+权限+用户系统。 (许多)用户可以分配给(许多)角色。 (许多)角色可以有一个(一个)父角色。可以为(许多)角色和(许多)用户分配(许多)权限。权限是允许或拒绝以及正在控制的操作或资源。我们也有 "Neutral" 许可,但这并不是真正必要的,而且往往会使本已复杂的系统变得更糟。
我构建的方式是更具体的权限覆盖不太具体的权限,因此用户胜过角色胜过父角色。在同一级别内,拒绝胜过允许。不相关的角色是 "same level",对任何一个对象的所有权限也是如此。没有单独的优先级控制使事情复杂化,角色的层次结构将其融入其中,并且特定于用户的任何内容都尽可能狭窄。
因此,为了回答您的问题,我认为您需要混合使用 2 和 3,或者很可能只是使用 3,因为您在一个级别上不会真正拥有冲突的权限。确切的权限应该总是获胜。然后我会说 Anything 打败任何人,因为 "Anything" 仍然特定于一个主题,而 "Anyone" 特定于资源而不是任何特定用户。 Any 显然是最不重要的,基本上作为默认值。
这与有权在资源端点上发出 GET/POST/PUT/DELETE 请求无关。这是关于某些用户对某些资源具有 GET/POST/PUT/DELETE 请求权限。
在我们的应用程序中,我们使用以下 sqlalchemy 架构将其称为访问控制列表 (ACL)
class ACL(db.Model):
__tablename__ = 'acl'
id = db.Column(db.Integer, primary_key=True)
res_id = db.Column(db.Integer, nullable=True)
res_type = db.Column(db.String(50), nullable=True)
permission = db.Column(db.String(20), nullable=True)
is_allowed = db.Column(db.Boolean, default=True)
users = db.relationship("User", secondary=acl_users)
created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow)
此ACL 与用户具有多对多关系,与每个资源具有多对一关系。这个 ACL 可以是四个东西:
- 如果res_id不为空且用户不是空列表,则称为"Exact",因为它指定了特定用户对特定资源的权限
- 如果res_id为空且用户不是空列表,则称为"Anything",因为它指定了特定用户对任何资源的权限
- 如果res_id不为空且用户为空列表,则称为"Anyone",因为它指定了任何用户对特定资源的权限
- 如果res_id为null且users为空列表,则称为"Any",因为它指定了任何用户对任何资源的权限
我不确定这种设计是否普遍,但它似乎拥有定义资源权限所需的一切。
问题如下:
如果一个资源有多个ACL,优先级应该是多少?
我们只有三个选择:
- 在 ACL table 上添加 'priority' 列并让它确定优先级。这种方法是有道理的,但是创建按优先级考虑 ACL 的 Fetch Collection 查询会变成一场噩梦。
- 错误 >> 正确。例如"Anyone" 错误胜过 "Exact" 正确。如果 "Anyone" 设置为 False,则没有用户对该资源具有权限。这最容易进行 Fetch Collection 查询。
- 确切 >> 任何人 >> 任何人 >> 任何人。即使 "Anyone" 为 False,如果 Exact user 设置为 True,则除该用户以外的所有人都具有权限。进行 Fetch Collection 查询既不容易也不不可能。
这三个选项中的哪一个最能反映许可的常见做法?
我不知道这些是否常见,总体上的模式与我过去看到的权限设置方式略有不同。 (顺便说一句,我在查找其他人如何对我自己的问题进行权限处理时发现了这个post,所以感谢您的不同观点!)
我以前的系统遵循非常标准的角色+权限+用户系统。 (许多)用户可以分配给(许多)角色。 (许多)角色可以有一个(一个)父角色。可以为(许多)角色和(许多)用户分配(许多)权限。权限是允许或拒绝以及正在控制的操作或资源。我们也有 "Neutral" 许可,但这并不是真正必要的,而且往往会使本已复杂的系统变得更糟。
我构建的方式是更具体的权限覆盖不太具体的权限,因此用户胜过角色胜过父角色。在同一级别内,拒绝胜过允许。不相关的角色是 "same level",对任何一个对象的所有权限也是如此。没有单独的优先级控制使事情复杂化,角色的层次结构将其融入其中,并且特定于用户的任何内容都尽可能狭窄。
因此,为了回答您的问题,我认为您需要混合使用 2 和 3,或者很可能只是使用 3,因为您在一个级别上不会真正拥有冲突的权限。确切的权限应该总是获胜。然后我会说 Anything 打败任何人,因为 "Anything" 仍然特定于一个主题,而 "Anyone" 特定于资源而不是任何特定用户。 Any 显然是最不重要的,基本上作为默认值。