Php 大型站点如何实现行级权限?

Php 大型站点如何实现行级权限?,php,mysql,acl,Php,Mysql,Acl,因此,我正在使用cakephp创建一个小型站点,并且我的ACL被设置为每次创建一段内容时,都会创建一个ACL规则来将内容的所有者链接到实际内容。这允许每个所有者编辑/删除自己的内容。这种方法似乎效率很低,因为数据库中有相当数量的ACL规则作为内容。我很好奇,拥有数百万条内容的大型网站如何解决这个问题?对于我工作过的大型网站,访问权限是在应用程序级别确定的。数据库将内容与用户记录相关联,然后在数据访问/业务逻辑层确定用户是否有足够的权限访问内容 对于一个有动态内容的大型网站,我认为这可能是最好的处

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

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

对于一个有动态内容的大型网站,我认为这可能是最好的处理方法

编辑:添加更具体的示例

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

由于此应用程序非常简单,因为它只提供文件服务,因此它只有三个数据库表,分别是:

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
正如您在这里看到的,我们使用参数化查询来获取用户所拥有的文件。此外,我们还将查询共享文件,以便向用户显示

现在假设每个文件都有自己的唯一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:好的,回到业务逻辑层,因为更复杂的应用程序需要更复杂的权限方案,这可能需要在业务逻辑层进行额外检查。

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

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

似乎很有趣,您能否再详细说明一下(例如添加一个如何实现此目标的示例)?
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)