如何使用Symfony 2创建类似以下权限系统的系统?

5

概述

该系统应能处理大量组织成嵌套类别的项目(见下面的视觉示例),同时使客户能够定义权限规则(见下面的权限规则)。它还应处理与任何项目无关的不同一般权限(例如,“可以查看特定页面?”或“可以邀请新成员?”)。

所有用户都被组织成群组。每个用户都有一个主要群组,但他也可能有一些额外的辅助群组。

少数用户可以配置为超级管理员,并且应允许做任何事情。

在决定用户是否被允许做某事时,权限继承如下:

  • 从主要群组权限开始
  • 允许用户的任何附加群组允许的所有权限
  • 如果定义了,请检查用户特定权限(独立于上述)。不必定义用户特定权限,如果未定义,则用户仅从群组权限继承权限

在定义群组权限时,客户端可以使用继承来表示类似以下内容:

  • 允许用户...
  • 编辑者具有用户的所有权限+ ...
  • 调解员具有编辑者的所有权限+ ...- ...
  • 管理员具有编辑者+调解员的所有权限

注意:我应该能够从数据库中请求当前用户可以编辑/查看的最后10个项目,每个项目的权限应由数据库决定,如果我可以基于存储在数据库中的信息做出决定,则不希望在应用程序级别过滤权限。

权限规则

规则可以依赖于项目的任何属性(例如,项目所有者的主要群组、创建时间、类别等),该信息存储在数据库中。

规则还可以依赖于当前用户的任何属性(例如,注册日期、成员邀请)、请求的操作(例如,查看、列出、重命名、撤消删除等)以及运行时已经可用的其他信息(例如,URL参数、配额限制、项目内容、服务器负载),该信息对PHP脚本可用。

请参见下面的示例规则。

数据库模式的视觉示例:

Category 1
   Nested Category A
      item x
   Nested Category B
      Deeply Nested Category
         item w
      item y
Category 2
   item z

目前,数据库模式如下,但如果需要,我可以更改它:(当然,这只是模式的一部分,还有其他表和字段)

items

id | title  | owner_id | category_id
====================================
1  | item x | 2        | 3
2  | item y | 1        | 4
3  | item z | 3        | 2
4  | item w | 1        | 5

分类:

id | parents | title
=====================================
1  | null    | Category 1
2  | null    | Category 2
3  | 1       | Nested Category A
4  | 1       | Nested Category B
5  | 1/4     | Deeply Nested Category

用户:

id | name | group | all_groups | is_super_admin
===============================================
1  | Tony | 5     | 5          | 1
2  | John | 5     | 5,8,6      | 0
3  | Mike | 4     | 4,7        | 0
4  | Ryan | 6     | 6          | 0

示例规则

以下规则仅是应该实施的真实世界案例的样本。

  • 用户可以在提交后5分钟内编辑自己的项目()
  • 用户“John”可以编辑“类别1”及其所有嵌套类别中的所有项目。
  • 编辑可以编辑除其所有者被标记为超级管理员的项目之外的所有项目。

请注意,这些规则可以像我的大多数规则一样在数据库级别上决定。

实现

我已经搜索了Symfony文档、stackoverflow等等。有很多有趣的文章和关于安全性和acl的问题,但我找不到处理这样一个系统的最佳方法。

显然,我需要某种类型的动态查询构建器来根据存储在数据库中的信息过滤行,根据定义的规则。我假设第二步(涉及到存储在数据库中的信息以外的信息,如当前服务器负载)可能是实现投票者(见本文此问题中的投票者示例),或者甚至更简单的解决方案(如依赖于请求路径的规则)。如果解决方案涉及处理权限的多个事项,请描述如何集成和使用它们。

问题

我想知道如何实现这样一个系统,请不要用链接回答Symfony文档或其他资源,而是请在回答之前阅读并理解我的情况。


4
你已经找到了适合你系统的设计吗?如果是的话,可以在这里发布吗?我正在实现类似的东西。谢谢! - mokagio
1
抱歉,经过数天寻找适用于Symfony的解决方案后,我放弃了... - Xuni
2
是的,我也是。我们实现了一个简单的自定义系统,受Symfony ACL启发,并使用了一些它们的基础组件。个人而言,我感到非常失望。 - mokagio
你们考虑过为每个权限使用角色吗?你可以将角色分配给用户和组,你也可以很容易地在表单中编辑角色。然后只需要使用投票器。 - JamesHalsall
1
权限实现的主要决定因素取决于实际授权检查的位置。默认情况下,Symfony使用基于用户角色的路由授权,但您可以在此基础上构建。我最近一直在开发一个复杂的ACL系统(因此我的评论有些迟到),该系统基于数据访问(我们正在处理儿童的PII)。控制器中的手动检查不够好(手动检查失败时会打开,我们需要失败关闭),因此我在Doctrine Entity级别内建立了自动检查(使用所有实体都基于的受保护前提条件)。 - Kal Zekdor
1个回答

1
我知道这个问题很老,但这个答案适用于Symfony 2.3+,所以我在这里发布它。
对于这种方法,您应该使用类似SecurityVoters的东西。
使用安全投票器,您可以实现任何您能想象到的访问控制逻辑。
投票器的工作原理类似于。
$this->get('security.authorization_checker')->isGranted('update',$post);

这将检查所有选民,他们可以操作帖子实体(请参阅文档),并使用所选择的策略(肯定、共识、一致)结合他们的投票来决定当前用户是否有权更新帖子(对于您的第一个规则示例)。

您可以为单个操作实现多个选民,并定义策略以决定结果投票。

您可以在存储库中存储所有组和权限,并在选民内使用Doctrine获取它们。

此外,您可以定义自定义角色层次结构以简化安全工作。

还可以阅读SecurityComponent上的这些文档。


1
请前往KnpUniversity https://knpuniversity.com/screencast/new-in-symfony3/voter,观看简短的教程,了解最重要的内容 :-) - MauganRa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接