我对 Symfony2 中实现访问控制列表的方式感到有些不安。
在 Zend Framework(版本 1 和 2)中, 的列表资源 和 的列表角色 被定义并且每个角色都被分配了它被允许访问的资源子集。因此资源和角色是 ACL 实现的主要词汇,而在 Symfony2 中并非如此,只有角色规则。
在旧版应用程序数据库中,我有表定义角色列表、资源列表和每个角色的允许资源列表(多对多关系)。每个用户都被分配了一个角色(管理员、 super 管理员、编辑等)。
我需要在 Symfony2 应用程序中使用这个数据库。
我的资源如下所示:ARTICLE_EDIT、ARTICLE_WRITE、COMMENT_EDIT 等。
我的 User
Symfony 中的实体实现了 Symfony\Component\Security\Core\User\UserInterface
接口(interface),因此具有 getRoles)
方法。
我打算用这个方法来定义允许的资源,也就是说我使用角色作为资源(我的意思是Zend Framework中所谓的资源在这里称为角色)。
你确认我应该使用这种方法吗?
这意味着我不再关心每个用户的角色(管理员、编辑……),而只关心它的资源。
然后我会使用 $this->get('security.context')->isGranted('ROLE_ARTICLE_WRITE')
在我的 Controller 中。
这是正确的方法吗?难道不是在 Symfony 中使用角色的一种规避方法吗?
最佳答案
多年后回答这个问题,很容易解决。
解决方案是混合角色和资源的概念。
让我们假设 role
表,一个 resource
表和 role_resource
定义了多对多关系。
用户存储在 user
table 。
以下是相应的 Doctrine 实体:
用户:
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface
{
/**
* @Id @Column(type="integer")
* @GeneratedValue
*/
private $id;
/**
* @ManyToOne(targetEntity="Role")
* @JoinColumn(name="role_id", referencedColumnName="id")
**/
private $role;
// ...
}
角色:
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;
// ...
}
所以现在的解决方案是实现
getRoles
的 UserInterface
这边走: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_WRITE
的资源):$this->get('security.context')->isGranted('ROLE_ARTICLE_WRITE')
关于symfony - Symfony2中如何实现角色/资源ACL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14194460/