最佳实践:设计权限系统

5
我目前正在使用Pyramid开发一个小型的Python网站。
但我不知道如何设计权限系统。
该系统应该非常灵活:我必须在许多不同的表之间建立连接。
我想到了创建一个名为PermissionCollection的表,而不是为每个变量编写一个权限表。这样可以使系统更加简洁:

PermissionCollection:

  • permissionCollectionId - 主键
  • onType = 枚举("USER","TEACHER","GROUP","COURSE"...)
  • onId = 整数

以及Permission表:

  • permissionId - 主键
  • key
  • value
  • permissionCollectionId - 外键

我将为源代码中可能存在的所有关系定义标准PermissionCollections,如果用户、课程、教师等具有特殊权限,则会创建新的PermissionCollection并将权限添加到其中。

我很新于Web编程,并不知道这种方法是否有用。或者是否存在类似的方法。我认为Pyramid ACL不是完成此任务的正确工具,对吗?


大多数RDBMS都有“GRANT” / “REVOKE”命令,用于允许对数据库中的表/模式进行各种级别的访问。其中一些甚至具有用户组的概念,这意味着您可以为整个组执行该命令。因此,您可能正在尝试在应用程序级别执行已经存在于数据库级别的操作(这将更加安全)。 - Clockwork-Muse
但是GRANT不是为我的数据库用户而设计的吗?而我的应用程序用户并不意味着数据库用户。 - Felix Scheinost
GRANT 是针对数据库用户的。但是,如果您编写了应用程序来检查权限(基于谁/什么登录到应用程序),那么您也可以将它们登录为特定的数据库用户(通常可以在连接字符串中提供这些信息)。这将有助于审计以及控制访问。 - Clockwork-Muse
1个回答

4

不确定您是否已经了解,但金字塔确实配备了一个非常好的权限系统。使用ACL进行授权。

如何处理它,这真的只取决于您... 您可以拥有一个ACL表

(对象ID、允许/拒绝、谁?(组、用户ID)、权限、顺序)

  • 对象ID是数据库中记录的唯一ID
  • 允许/拒绝是该ACE应该执行的操作... 允许或拒绝访问
  • 谁?可以是组、用户名或任何您想要的,例如system.everyone代表每个人
  • 权限是view_config中的权限参数
  • 顺序是一个重要的事情,顺序很重要

例如

__acl__ = [
(Deny, Everyone, 'view'),
(Allow, 'group:admin', 'view')
]

这个示例将始终拒绝查看,即使对于管理员也是如此...一旦Pyramid找到了能告诉你是否可以查看记录的东西,它就会自动停止搜索。
__acl__ = [
(Allow, 'group:admin', 'view'),
(Deny, Everyone, 'view')
]

这将允许每个管理员查看,但不允许其他人查看。这就是为什么您必须记住ACE的顺序。
实际上,有趣的部分在这里。这很好。您已经将acl映射到数据记录中。例如,当您加载页面时...您将需要加载acl并将它们设置在您的对象中。
myobject.__acl__ = load_acls(myobject) 

如果您拥有一个数据树,甚至可以不设置acls。
例如,您拥有一个类似于这样的网站。
root
  \--pages with acl
      +---- page1  without acl
      \---- page2  with acl
当您访问page1时,它将检查acl是否存在,如果找不到,则会检查parent是否有acl,如果parent有acl,则会检查其权限,如果没有,则会检查其parent直到达到根目录。如果找不到权限,我不确定会发生什么...我猜它要么会给您一个禁止错误,要么会给您一个谓词错误,表示无法找到适当的视图。
也就是说,为了使其工作,您必须创建一个知道其父级的位置感知对象。
但是为什么要这样做呢?
您可以为任何对象设置acl,并对数据库中的每个对象进行非常精细的控制,以确定谁可以观看或不观看每个对象。您还可以直接在类对象中放置acl,而无需使用数据库。
只要您的acl在属性acl中,金字塔就能够处理它。重要的不是您如何获得它。
看看这个。

http://pyramid.readthedocs.org/en/1.3-branch/tutorials/wiki/authorization.html


好的,谢谢。我也可以使用我的表格吗?在你的方法中:应用程序如何确定who:1表示具有ID 1的用户一组ID为1的用户?因此,我只需编写一个函数,在遍历树中的每个元素上生成此acl元组。我可以在构造函数中加载acl吗? - Felix Scheinost
你可以在任何地方加载 ACL,只要你的实例有__acl__设置为元组列表 (ACE)。 - Loïc Faure-Lacroix
当金字塔发现它可以允许或拒绝对元素的访问时,它将返回。在某些情况下,如果您具有简单的权限,则顺序并不重要。但是我的上面的例子...如果您首先拒绝所有人,然后仅允许管理员进入第二个...它将拒绝所有人然后返回。它甚至不会检查允许管理员。因此,如果您想控制ACL中哪个ACE首先出现,设置顺序非常重要。此外,如果您进入development.ini文件,可以启用auth debug。 - Loïc Faure-Lacroix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接