【问题标题】:How do large sites accomplish row-level permissions?大型网站如何实现行级权限?
【发布时间】:2011-01-10 21:52:11
【问题描述】:

所以我正在使用 cakephp 制作一个小型网站,并且我的 ACL 设置为每次创建一条内容时,都会创建一条 ACL 规则来将该段内容的所有者链接到实际内容。这允许每个所有者编辑/删除他们自己的内容。这种方法看起来效率很低,因为在数据库中存在与内容等量的 ACL 规则。我很好奇,拥有数百万条内容的大型网站如何解决这个问题?

【问题讨论】:

    标签: php mysql acl


    【解决方案1】:

    我在大型网站上工作的访问权限是在应用程序级别确定的。数据库将内容与用户的记录相关联,然后在数据访问/业务逻辑层确定用户是否有足够的权限访问内容。

    对于具有动态内容的大型网站,我认为这可能是处理它的最佳方式。

    编辑:添加一个更具体的例子。

    示例: 好吧,假设我们有一个简单的文件存储站点,用户只能访问他们的数据或其他用户明确与他们共享的数据。

    由于这个应用程序相当简单,因为它只是提供文件,它只有三个数据库表,它们是:

    Users Table which has columns:
          UserId <int>  PK
          UserName <varchar>
          HashedPassword <varchar>
    Files Table which has columns:
          FileId <int>  PK
          FileOwnerId <int> FK (this has a foreign key relationship with UserId in the users table)
          FileName <varchar>
          MimeType <varchar>
          FileData <blob>
    SharedFile reference table which has columns:
          SharedFileIndex <int> PK
          FileId <int> FK
          UserId <int> FK
    

    现在,我们要在数据访问层中定义一些基本规则,即当用户登录时,他们可以访问他们拥有的文件以及其他用户与他们共享的文件。因此,无论是通过存储过程还是构建查询以发送到数据库服务器,我都会确保我的查询只返回他们有权访问的那些记录。

    这里是用户登录时的基本 GetUsersFileList sql 查询:

    SELECT FileId, FileName, FileType
    FROM Files
    WHERE FileOwnerId = @UserId
    

    正如您在此处看到的,我们使用参数化查询来获取用户拥有的文件。此外,我们还将查询共享文件以向用户显示。

    现在,如果我们假设每个文件都有自己唯一的 url,例如:

    http://mydomain.com/filehandler.php?fileId=123546
    

    然后当我们尝试获取文件时,我们使用与上面类似的查询来尝试获取文件数据:

    SELECT FileName, FileType, FileData
    FROM Files
    LEFT OUTER JOIN SharedFiles on Files.FileId = SharedFiles.FileId
    WHERE Files.FileId = @FileId AND (FileOwnerId = @UserId OR SharedFiles.UserId = @UserId)
    

    因此,您会看到,当我们尝试获取文件时,我们仍在查询中使用 UserId,因此,如果用户没有与他们共享文件或者他们不是文件的所有者,则查询的结果将为 0 行。

    因此权限取决于用户在数据库中映射到的对象,但实际执行是通过在提供内容之前仔细编写数据访问代码和/或在业务逻辑层中进行额外检查来完成的。

    EDIT2:我最熟悉 MSSQL,所以我上面的查询是在 T-SQL 中的,所以对于 MySql 来说语法可能有点偏离。

    EDIT3:将业务逻辑层替换为数据访问层,如本例所示,唯一进行的检查是在数据访问查询本身内。

    EDIT4:好的,请参考业务逻辑层,因为更复杂的应用程序需要更复杂的权限方案,这可能需要在业务逻辑层中进行额外检查。

    【讨论】:

    • 看起来很有趣,您能否详细说明一下(例如添加一个小示例说明您将如何完成此操作)?
    【解决方案2】:

    您可以为每组不同的权限设置一个单独的 ACL,而不是为每个内容元素设置一个单独的 ACL。给定用户的大多数内容项将具有相同的权限,因此它们都可以指向相同的 ACL。这也可以让您缓存权限检查(例如“用户 123 有权读取 ACL 456”)。最后,您将拥有非常少的 ACL——只有所有标准的 ACL 和少数例外。

    【讨论】:

    • 你能说得更详细些吗?
    【解决方案3】:

    同样的规则适用于大型和小型网站 - 如果您想要更具体的控制,您必须在数据库中存储更多数据。您尝试解决的问题 [允许用户仅管理他们的内容] 可以使用表之间的简单用户 ID 链接 [例如 users.id articles.userId] 来解决,无需将每一行与用户链接。我建议使用更通用的规则并仅将例外情况(例如允许指定用户编辑其他用户的内容)存储为外部数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-05
      • 1970-01-01
      • 2013-10-03
      • 2016-05-11
      • 1970-01-01
      • 2010-12-08
      • 1970-01-01
      • 2012-06-09
      相关资源
      最近更新 更多