(Security)怎样去使用Access Control Lists-ACLs(3.0)

在复杂的应用中,你可能经常面临访问权限决策不仅仅取决于请求者本人(Token)还牵涉到了被申请的对象的问题。这也是 ACLs 系统被制作出来的原因所在。

ACL的替代选择

使用ACL并不平凡,而对于较简单的情况下,他可能矫枉过正。如果你的许可逻辑可以通过一些简单的代码来完成(例如,检查博客是不是当前用户的)那么可以考虑使用voter。一个voter可以决定对象的访问,你能够使用它来完成复杂的决定,有效的实现自己的ACL。此外,强制授权(比如 isGranted 部分)就会看起来和你在本章所看到的这个条目极其相似,但是你的 voter 类就会在幕后控制判定逻辑了,而不是 ACL 系统。

想象一下,你正在设计一个博客系统,而看你文章的人可以评论它。现在,你希望用户能够编辑自己的评论,而不是其他用户的;此外,你自己希望能够编辑所有人的评论。在这种情况下,你要对comment域对象限制访问。使用symfony你可以用几种方式来做到这一点,其中两个基本的方式是(非详尽):

在你的逻辑方法中实现安全:基本上这意味着,评论最为参考,比对所有用户谁有权访问,并比对用户提供的Token。

角色来实现安全:这种方法是,为每一个评论对象添加一个角色,即ROLE_COMMENT_1,ROLE_COMMENT_2 等。

这两种方法都非常有效。然而,把你的验证代码和逻辑代码放到一起,会使他不能重用,并增加单元测试的难度。此外,如果很多用户会访问一个域对象,你的代码可能会遇到性能问题。

幸运的是,这里有一种更好的方式,你在下面就可以看到。

 

准备

现在,在你终于要才去行动之前,你需要做一些准备。首先,你需要配置ACL系统的连接以供使用:

标注:这个ACL系统必须有一个链接,链接可以是Doctrine DBAL(默认使用)也可以是Doctrine MongoDB(用于MongoDBAclBundle)。然而,这并不意味着你必须使用Doctrine ORM或者ODM来映射你的域(domain)对象。你可以用你喜欢的任何方式来映射对象,比如 DoctrineORM,MongoDB ODM,Propel,rawSQL 等等。选择权在你手里。

在连接方式确定好之后,你必须导入数据机构。幸运的是,这个任务,只需要一行命令:

 

开始入门

上面的场景,现在你就可以用acl去实现它。

一旦ACL被创建,你可以通过创建一个Access Control Entry(ACE)来巩固实体和你的用户之间的关系,来访问对象。

 

创建一个ACL并添加一个ACE

在这段代码中,有几个重点。在这里我着重讲两处:

首先,你可能会注意到->createAcl()没有直接传入域对象,但他实现了ObjectIdentityInterface。这个间接的步骤使你在没有实际的域对象实例时,也可以让ACL工作。这在你想要检查一大批对象的权限,将会起到很大的作用。

另一个有趣的部分就是调用->insertObjectAce()。在这个例子中,你允许当前登录用户去操作自己的评论。MaskBuilder::MASK_OWNER 是一个提前定义好的整数位掩码;不必担心掩码生成器会抽象大部分细节,但你能够在一个数据库行存储很多不同的权限,从性能上给予很多提升。

提示:ACEs 的检查顺序是很有意义的,作为一项通用的准则,你应该在最开始设立更多的入口。

 

访问检查

在这个例子中,你检查用户是否有EDIT(编辑)权限。在内部,symfony映射权限到多个整数位掩码,并检查用户是否拥有这些码。

你可以建立32位的基本权限-位掩码(根据你操作系统php会有所不同在30-32之间)。此外,你还可以定义累加权限。

累加权限

在上面的第一个例子中,你只授予用户OWNER权限。尽管这样会使用户有效的执行任意的操作,例如查看,编辑域对象等。但在某些情况下,您可能想要明确的指定这些权限。

MaskBuilder就能够很容易的创建这些位掩码,并把几个权限结合在一起:

此整数位掩码可以被用来授予用户您在上面添加的基础权限:

现在的用户可以查看,编辑,删除,并取消删除的对象。

发表评论