资源列表授权的最佳实践是什么?

时间:2008-10-04 16:22:32

标签: security authorization

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

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

我有两个问题:

  1. 一旦检索到资源,就很容易授权用户,但是如何在可用资源列表上有效地执行授权?而且,

  2. 这种授权可以与应用程序的核心分开吗?也许进入一个单独的服务?一旦分开,你怎么能过滤这样的查询,比如'让我看到所有我能看到的文件,像[SomeSearchTerm]这样的标题?在我看来,你的独立系统必须复制很多参考数据。

3 个答案:

答案 0 :(得分:5)

您可能有兴趣阅读this article by Steffen Bartsch。它总结了Ruby on Rails的所有授权插件,我相信它可以帮助您找到解决方案(尽管本文是关于Rails插件的,这些概念可以在Rails之外轻松导出)。

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

  • 一方面,您定义角色(例如“访客”,“管理员”......)。您的用户与这些角色相关联(以多对多关系)。您将这些角色映射到特权(再次以多对多关系)。每个权限都与给定的上下文相关联。例如,角色“ visitor ”可能具有“读取文档”的权限。在此示例中,“ read ”是权限,它将应用于“ documents ”上下文。
    • 注意:在Steffen的插件中,您可以定义角色的层次结构。例如,您可能希望“ global_admin ”角色包含“ document_admin ”角色,以及“ comment_admin ”角色等。
    • 您还可以定义权限的层次结构:例如,“ manage ”权限可以包括“ read ”,“ update ” ,“添加”和“删除”权限。
  • 另一方面,您根据特权上下文对您的应用程序进行编码,而不是根据角色。例如,显示文档的操作应仅检查用户是否具有“文档”上下文中“读取”的权限(无需检查用户是否拥有“访客”角色或任何其他角色)。这大大简化了您的代码,因为大多数授权逻辑都是在其他地方提取的(甚至可能由其他人定义)。

用户角色定义与应用程序级权限定义之间的这种分离可确保您的代码在每次定义新角色时都不会更改。例如,以下是访问控制在控制器中的外观简单:

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 ”权限,但< strong>仅如果用户是文档的作者。这条规则的声明可能如下所示:

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

这就是它的全部!您现在可以获得允许用户更新的所有文档,如下所示:

Document.with_permissions_to(:update)

由于“ manage ”权限包含“ update ”权限,因此将返回作者为当前用户的文档列表。

当然,并非每个应用程序都需要这种程度的灵活性......但是你可能会这样做。

答案 1 :(得分:0)

我通常有这样的架构

用户--∈UserDocuments∋--文件

然后我创建一个视图“ProfiledDocuments”

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

然后始终使用UserId过滤器在ProfiledDocuments上运行搜索查询。使用适当的索引,它运作良好。

如果您需要更复杂的权限,可以使用UserDocuments中的多个表来指定权限类型。

答案 2 :(得分:0)

虽然你的问题很详细,但实际上有一些缺失的背景 什么定义了用户拥有权限的文档?用户只能编辑他自己的“自己的”文件吗?这里有基于角色的机制吗?它是否更加面向MAC(即用户可以看到安全级别)?是否有数据的定义属性(例如部门)?

所有这些问题可以提供更好的图片,并提供更具体的答案。

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

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