我想听听一些关于优化我们的架构以实现以下目标的最佳方法的想法。
我们有许多对象/数据库条目(事件,场地等),其中一些有子对象(意味着相同的权限适用 - 图像,元素等)
用户可以属于群组,因此所有人,只有一个群组,只有一个用户,可以编辑/查看事件,场所等父对象。
目前,我们有一个用户,用户组和组表来管理用户和组。
每个父对象,例如场地,作为user_id和group_id的列。
工作正常(在symfony 1.4中)但它很乱 - 任何事情的每个查询都必须进行复杂的连接以获得可能的组等...我们想找到一种更简单的方法。
我对Sf2 ACL组件感到非常兴奋,但我一遍又一遍地告诉我不应该用它来查找用户可以管理的对象 - 而是我应该使用ACL来查明用户是否被允许管理自己的对象(似乎没有用,但无论如何)。
我发现在网上进行的所有替代尝试都是为了从db中提取所有对象,然后通过ACL过滤 - 这对于妈妈和流行网站来说很可爱 - 不会发生在一百万个对象上。
所以...我很想听听我们如何做到这一点的想法 - 我们也愿意让symfony留下具有可扩展ACL解决方案的东西,但到目前为止还没有找到任何东西(php或ruby)这么开放虽然我们很乐意继续使用Sf。请注意,我们打算在重要的情况下使用MongoDB。
答案 0 :(得分:11)
根据我的理解,ACL用于为特定场景提供对特定人员的特定对象的访问权限。你所描述的内容更为通用,但它只是偏离了Symfony2为安全性所概述的内容(此人具有“管理员”角色,但仅适用于特定组中包含的对象)。
ACL不应该用于存储大量的东西,因为如果它太大,检查就会变得昂贵。因此,在添加新用户时,或者甚至在组中添加新对象时,默认情况下会抛出一堆东西(如果使用ACL,则无论何时创建一个组,都必须向组中的每个人添加一个条目一段时间之后会对性能产生负担......
我目前正在研究将Symfony2用于网络应用程序的可能性,但是我也遇到了这种安全问题,因为我们有类似的需求。我不是Symfony2的专家,但从我所看到的,你可能有几个选择:
创建一个选民来处理这个问题。选民允许您检查授权令牌,并根据您的处理方式返回授予或拒绝访问权限。因此,您可以创建一个自定义选民,用于检查用户的组并尝试将其与该对象所在的组进行匹配。如果是这样,如果选民对当前检查无效,则返回ACCESS_GRANTED,否则返回ACCESS_DENIED或ACCESS_ABSTAIN。编辑:以下是Symfony2选民食谱的链接:http://symfony.com/doc/current/cookbook/security/voters.html
可能还想研究SecurityContext接口。这提供了“isGranted()”方法,用于确定对对象的访问。如果选民不够简单,你可能不得不走创建一个新的SecurityContext类的路线;我认为这会更复杂一些。
答案 1 :(得分:1)
自从我发布原始答案以来已经有一段时间了,但我想跟进另一个我们目前使用的解决方案。
虽然Symfony提供了一个安全/ ACL层,但你没有 使用它,或者至少完全使用它。
在您的代码中的任何时间点,您都可以抛出Symfony\Component\Security\Core\Exception\AccessDeniedException
,安全层将会启动"并为您处理,例如将用户重定向到登录页面等。
某些此类交互可能需要更高级的防火墙设置才能完全按照您的需要运行。
长话短说,虽然Symfony提供了一些很好的机制和功能来帮助构建ACL,但您不必努力使您的数据和流程适合他们定义的内容。
以我们的系统为例,我们的系统中包含帐户,角色和组(以及权限)。我们还将部分数据划分为部门。虽然用户可以拥有全局级别的角色和权限,但他们也可以拥有特定于部门的访问权限。这种设置使用内置的Symfony ACL功能和访问检查工具几乎无法使用(并不意味着他们的工具无用,实际上它们很棒,它们不适合我们的用例)。因此,我们构建了自己的服务(利用一些微调查询),我们传递了有关支票的相关数据,并在检查失败时抛出相应的Symfony\Component\Security\Core\Exception\AccessDeniedException
。