如何在Symfony2中实现角色/资源ACL
我对在Symfony2中实现访问控制列表的方式感到有点不安 在Zend框架(版本1和版本2)中,定义了资源列表和角色列表,并为每个角色分配了允许其访问的资源子集。因此,资源和角色是ACL实现的主要词汇表,而在Symfony2中则不是这样,在Symfony2中,只有角色起作用 在遗留应用程序数据库中,我有定义角色列表、资源列表和每个角色允许的资源列表(多对多关系)的表。每个用户都被分配了一个角色(管理员、超级管理员、编辑等) 我需要在Symfony2应用程序中使用此数据库。 我的资源是这样的:文章编辑、文章写作、评论编辑等等 Symfony中的My如何在Symfony2中实现角色/资源ACL,symfony,acl,Symfony,Acl,我对在Symfony2中实现访问控制列表的方式感到有点不安 在Zend框架(版本1和版本2)中,定义了资源列表和角色列表,并为每个角色分配了允许其访问的资源子集。因此,资源和角色是ACL实现的主要词汇表,而在Symfony2中则不是这样,在Symfony2中,只有角色起作用 在遗留应用程序数据库中,我有定义角色列表、资源列表和每个角色允许的资源列表(多对多关系)的表。每个用户都被分配了一个角色(管理员、超级管理员、编辑等) 我需要在Symfony2应用程序中使用此数据库。 我的资源是这样的:文章
User
实体实现了Symfony\Component\Security\Core\User\UserInterface
接口,因此具有getRoles)
方法
我打算使用这个方法来定义允许的资源,这意味着我使用角色作为资源(我的意思是在Zend框架中称为资源的东西在这里称为角色)
你确认我应该使用这种方法吗
这意味着我不再关心每个用户的角色(管理员、编辑等),而只关心其资源
然后我会在我的控制器中使用$this->get('security.context')->isgrated('ROLE\u ARTICLE\u WRITE')
这是正确的方式吗?在Symfony中使用角色不是一种规避的方式吗?我认为这将回答您的问题
多年后,要回答这个问题,这是很容易解决的 解决方案是混合角色和资源的概念 让我们假设定义了
角色
表、资源
表和角色资源
多对多关系
用户存储在user
表中
以下是相应的条令实体:
用户:
角色:
资源:
class Resource
{
/**
* @Id @Column(type="integer")
* @GeneratedValue
*/
private $id;
/** @Column(type="string") */
private $name;
// ...
}
因此,现在的解决方案是通过以下方式实现UserInterface
的getRoles
:
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Role\Role;
class User implements UserInterface
{
// ...
/**
* @var Role[]
**/
private $roles;
/**
* {@inheritDoc}
*/
public function getRoles()
{
if (isset($this->roles)) {
return $this->roles;
}
$this->roles = array();
$userRole = $this->getRole();
$resources = $userRole->getResources();
foreach ($resources as $resource) {
$this->roles[] = new Role('ROLE_' . $resource);
}
return $this->roles;
}
}
通过这种方式,可以通过这种方式检查属于当前用户的资源(考虑到有一个资源的名称是ARTICLE\u WRITE
):
class Role
{
/**
* @Id @Column(type="integer")
* @GeneratedValue
*/
private $id;
/** @Column(type="string") */
private $name;
/**
* @ManyToMany(targetEntity="Resource")
* @JoinTable(name="role_resource",
* joinColumns={@JoinColumn(name="role_id", referencedColumnName="id")},
* inverseJoinColumns={@JoinColumn(name="resource_id", referencedColumnName="id")}
* )
**/
private $resources;
// ...
}
class Resource
{
/**
* @Id @Column(type="integer")
* @GeneratedValue
*/
private $id;
/** @Column(type="string") */
private $name;
// ...
}
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Role\Role;
class User implements UserInterface
{
// ...
/**
* @var Role[]
**/
private $roles;
/**
* {@inheritDoc}
*/
public function getRoles()
{
if (isset($this->roles)) {
return $this->roles;
}
$this->roles = array();
$userRole = $this->getRole();
$resources = $userRole->getResources();
foreach ($resources as $resource) {
$this->roles[] = new Role('ROLE_' . $resource);
}
return $this->roles;
}
}
$this->get('security.context')->isGranted('ROLE_ARTICLE_WRITE')