5

发布和/或协作应用程序通常涉及共享对资源的访问。在门户中,用户可能被授予对某些内容的访问权限作为组的成员或由于明确的访问权限。完整的内容集可以包括公共内容、群组成员内容和私人用户内容。或者,对于协作应用程序,我们可能希望将资源作为工作流程的一部分传递或共享文档的保管以进行编辑。

由于大多数应用程序将这些资源存储在数据库中,因此您通常会创建查询,例如“获取我可以编辑的所有文档”或“获取我可以看到的所有内容”。其中“可以编辑”和“可以查看”是用户的权限。

我有两个问题:

  1. 检索资源后,对用户进行授权非常容易,但是如何有效地对可用资源列表执行授权呢?和,

  2. 这种授权可以脱离应用的核心吗?也许进入一个单独的服务?分离后,您如何过滤诸如“获取所有我可以看到的标题为 [SomeSearchTerm] 的文档”之类的查询?在我看来,您的单独系统将不得不复制大量参考数据。

4

3 回答 3

5

您可能有兴趣阅读Steffen Bartsch 的这篇文章。它总结了 Ruby on Rails 的所有授权插件,我相信它会帮助您找到解决方案(虽然本文是关于 Rails 插件的,但这些概念很容易在 Rails 之外导出)。

Steffen 还构建了自己的插件,称为“声明式授权”,它似乎符合您的需求,恕我直言:

  • 一方面,您定义角色(例如“访客”、“管理员”……)。您的用户与这些角色相关联(以多对多关系)。您将这些角色映射到权限(同样是多对多关系)。每个特权都链接到给定的上下文。例如,角色“访问者”可能具有“阅读文档”的权限。在本例中,“ read ”是权限,它应用于“ documents ”上下文。
    • 注意:在 Steffen 的插件中,您可以定义角色的层次结构。例如,您可能希望“ global_admin ”角色包括“ document_admin ”角色,以及“ comment_admin ”角色等。
    • 您还可以定义权限层次结构:例如,“管理”权限可以包括“读取”、“更新”、“添加”和“删除”权限。
  • 另一方面,您根据权限上下文而不是角色来编写应用程序的思维方式。例如,显示文档的动作应该只检查用户是否具有在“文档”上下文中“阅读”的权限(无需检查用户是否具有“访问者”角色或任何其他角色)。这极大地简化了您的代码,因为大多数授权逻辑都在其他地方提取(甚至可能由其他人定义)。

用户角色的定义和应用程序级权限的定义之间的这种分离保证了您的代码不会在每次定义新角色时发生变化。例如,以下是控制器中访问控制的简单程度:

class DocumentController [...]
  filter_access_to :display, :require => :read
  def display
    ...
  end
end

在视图内部:

<html> [...]
  <% permitted_to?(:create, :documents) do %>
  <%= link_to 'New', new_document_path %>
  <% end %>
</html>

Steffen 的插件还允许对象级(即行级)访问控制。例如,您可能想要定义一个角色,如“ document_author ”,并赋予它“documents”的“ manage 权限,但前提是用户是文档的作者。该规则的声明可能如下所示:

role :document_author do
  has_permission.on :documents do
    to :manage
    if_attribute :author => is {user}
  end
end

这里的所有都是它的!您现在可以像这样获取允许用户更新的所有文档:

Document.with_permissions_to(:update)

由于“管理”权限包括“更新”权限,这将返回作者为当前用户的文档列表。

当然,并非每个应用程序都需要这种级别的灵活性……但您可能需要。

于 2008-11-23T02:27:30.193 回答
0

I generally have a schema like this

Users −−∈ UserDocuments ∋−− Documents

Then I create a view "ProfiledDocuments"

SELECT <fields> 
FROM Documents d 
INNER JOIN UserDocuments ud on ud.DocumentId = d.Id 
INNER JOIN Users u ON u.Id = ud.UserId

Then run the search queries on ProfiledDocuments always using a UserId filter. With appropriate indexes it works well enough.

If you need more complex permissions, you can do it with an extra field in the UserDocuments many to many table which specifies the kind of permission.

于 2008-10-04T16:36:47.643 回答
0

尽管您的问题非常详尽,但实际上缺少一些上下文。
什么定义了用户有权访问的文档?用户只能编辑他的“自己的”文件吗?这里有基于角色的机制吗?它是否更面向 MAC(即用户可以看到一定程度的安全性)?数据是否有定义属性(例如部门)?

所有这些问题加在一起可能会提供更好的画面,并提供更具体的答案。

如果文档由特定用户“拥有”,则非常简单 - 为文档设置一个“所有者”字段。然后,查询用户拥有的所有文档。
同样,如果您可以预先定义具有访问权限的命名用户(或角色)列表,您可以查询文档、授权用户/角色列表和用户(或他的角色)之间的连接列表。
如果用户根据其部门(或其他类似文档的属性)获得权限,您可以对其进行查询。
同样,您可以查询安全级别等于或低于用户权限的所有文档。如果这是动态工作流,则每个文档通常都应标有其当前状态和/或下一个预期步骤;哪些用户可以执行下一步只是另一个特权/角色(与上述相同)。
然后,当然,你会想要在所有这些和公共文件之间做一个 UNION ALL ......

顺便说一句,如果我没有说清楚,这不是一个简单的问题 - 帮自己一个忙,找到预先构建的基础设施来为你做这件事。即使以简化您的授权模式为代价。

于 2008-10-05T00:48:09.167 回答