发布和/或协作应用程序通常涉及共享对资源的访问.在门户中,可以授予用户作为组成员或由于显式访问而对某些内容的访问权.完整的内容集可以包括公共内容,组成员资格内容和私有用户内容.或者,对于协作应用程序,我们可能希望将资源作为工作流的一部分传递或共享文档的保管以进行编辑.
由于大多数应用程序将这些资源存储在数据库中,因此通常会创建诸如"获取我可以编辑的所有文档"或"获取我能看到的所有内容"之类的查询."可以编辑"和"可以看到"的是用户的权限.
我有两个问题:
一旦检索到资源,就很容易授权用户,但是如何在可用资源列表上有效地执行授权?和,
这种授权可以与应用程序的核心分开吗?也许进入一个单独的服务?一旦分开,你怎么能过滤这样的查询,比如'找到我能看到的所有文件,像[SomeSearchTerm]这样的标题?在我看来,你的独立系统必须复制大量的参考数据.
MiniQuark.. 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
在视图中:
[...] <% permitted_to?(:create, :documents) do %> <%= link_to 'New', new_document_path %> <% end %>
Steffen的插件还允许对象级(即行级)访问控制.例如,您可能希望定义一个角色,如" document_author ",并给它" 管理上","特权的文件 ",但只有当用户是文档的作者.此规则的声明可能如下所示:
role :document_author do has_permission.on :documents do to :manage if_attribute :author => is {user} end end
这里的所有都是它的!您现在可以获取允许用户更新的所有文档,如下所示:
Document.with_permissions_to(:update)
由于" 管理 "权限包括" 更新 "权限,因此将返回其作者是当前用户的文档列表.
当然,并非每个应用程序都需要这种级别的灵活性......但是你的应用程序可能会.
您可能有兴趣阅读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
在视图中:
[...] <% permitted_to?(:create, :documents) do %> <%= link_to 'New', new_document_path %> <% end %>
Steffen的插件还允许对象级(即行级)访问控制.例如,您可能希望定义一个角色,如" document_author ",并给它" 管理上","特权的文件 ",但只有当用户是文档的作者.此规则的声明可能如下所示:
role :document_author do has_permission.on :documents do to :manage if_attribute :author => is {user} end end
这里的所有都是它的!您现在可以获取允许用户更新的所有文档,如下所示:
Document.with_permissions_to(:update)
由于" 管理 "权限包括" 更新 "权限,因此将返回其作者是当前用户的文档列表.
当然,并非每个应用程序都需要这种级别的灵活性......但是你的应用程序可能会.