发布于 2015-12-06 07:29:57 | 226 次阅读 | 评论: 0 | 来源: 网络整理
本章的目的是给出一个更深入的 ACL 系统的观点,并解释其背后的一些设计决策。
Symfony 的对象实例的安全功能是基于一个访问控制列表的概念。每一个域对象实例都有自己的 ACL。ACL 实例有一个详细的列表,访问控制项(ACEs),用于访问决策。Symfony 的 ACL 系统集中在两个主要目标:
为您的域对象提供一种方式来有效地检索大量的 ACLs / ACEs,并修改它们;
正如第一点中所暗示的,Symfony 的 ACL 系统的主要功能之一是以高性能的方式检索 ACLs / ACEs。这是非常重要的,因为每个 ACL 可能有一些 ACEs,并以树形方式继承另一个 ACL。因此,ORM 是没有作用的,代替使用 Doctrine 的 DBAL 直接连接的默认实现。
ACL 系统是完全脱离您的域对象。他们甚至不需要存储在同一个数据库中,或在同一台服务器上。为了实现这种分离,ACL 系统对象通过对象标识对象表示。每次你想为一个域对象检索 ACL,ACL 系统将首先从你的域对象创建一个对象的身份,然后通过这个对象身份 ACL 提供者进行进一步处理。
这是模拟对象身份标识,但在您的应用程序中代表一个用户或角色。每个角色或用户有自己的安全标识。
默认实现使用五个数据库表如下所示。这些表按行数递增的顺序排在一个典型的应用程序中:
访问控制条目在他们的应用中可以有不同的适用范围。在 Symfony 中,基本上有两个不同的范围:
类范围:这些条目适用于所有从属于相同类的对象。
有时,你会发现只需要为对象的一个特定字段申请一个 ACE。假设您想要一个只对管理员而不是您的客户服务可见的 ID。为了解决这个普遍的问题,增加了两个 sub-scopes:
Class-Field-Scope:这些条目适用于所有从属于相同类的对象,但只有特定字段的对象。
预先授权决策,即做出决定之前任何安全方法被调用(或安全措施),已证实 AccessDecisionManager 服务是被使用的。AccessDecisionManager 也被用于实现基于角色的授权决策。就像角色,ACL 系统添加了一些新的属性,可以用来检查不同的权限。
属性 | 含义 | 整数位掩码 |
---|---|---|
VIEW | 是否有人可以查看域对象。 | VIEW, EDIT, OPERATOR, MASTER, or OWNER |
EDIT | 一个人是否可以更改域对象。 | EDIT, OPERATOR, MASTER, or OWNER |
CREATE | 一个人是否被允许创建域对象。 | CREATE, OPERATOR, MASTER, or OWNER |
DELETE | 一个人是否被允许删除域对象。 | DELETE, OPERATOR, MASTER, or OWNER |
UNDELETE | 删除的人是否可以恢复以前删除的域对象。 | UNDELETE, OPERATOR, MASTER, or OWNER |
OPERATOR | 是否有人允许执行所有上述操作。 | OPERATOR, MASTER, or OWNER |
MASTER | 是否有人允许执行所有上述操作,并且允许任何上述权限授予其他人。 | MASTER, or OWNER |
OWNER | 是否有人拥有域对象。OWNER 可以执行上述任何操作并授予 MASTER 和 OWNER 权限。 | OWNER |
AccessDecisionManager 属性的使用就像角色一样。通常,这些属性事实上代表一个聚合的整数位掩码。使用整数位掩码另一方面,ACL 系统内部在数据库中有效存储用户的权限,并使用极快的位掩码操作执行访问检查。
上述许可映射绝不是静态的,并且理论上可以完全被取代。然而,它应该囊括大多数您遇到的问题,以及与其他包的互操作性。鼓励您坚持它们原本被设想的意义。
后授权决策在一个安全的方法被调用后做出,并且通常涉及被这样的方法返回的域对象。在调用完成后,提供者也允许修改,或在返回之前过滤域对象之前返回。
由于当前的 PHP 语言的局限性,没有 post-authorization 功能构建为核心的安全组件。然而,有一个实验 JMSSecurityExtraBundle 增加这些功能。如果您想了解更多关于这是如何完成的的信息,请看它的相关文档。
ACL 类提供了两个方法来确定是否一个安全标识需要位掩码,isGranted 和 isFieldGranted。当 ACL 通过这些方法之一收到授权请求,它代表这个请求 PermissionGrantingStrategy 的实现。这允许您替换访问决策的方式而不修改 ACL 类本身。
PermissionGrantingStrategy 首先检查你所有的 object-scope ACEs。如果没有适用的,class-scope ACEs 将被检查。如果没有适用的,那么这个过程会重复地对父 ACL 的 ACEs 进行。如果没有父亲 ACL 存在,将会抛出一个异常。