如何在Symfony2中实现角色/资源ACL

6

我对Symfony2中访问控制列表的实现方式感到有些困惑。

在Zend Framework(版本1和2)中,定义了一组资源和一组角色,并为每个角色分配了它可以访问的资源子集。因此,资源和角色是ACL实现的主要词汇,但在Symfony2中并非如此,只有角色起作用。

在遗留应用程序数据库中,我有定义角色列表、资源列表和每个角色允许访问的资源列表(多对多关系)的表。每个用户被分配一个角色(管理员、超级管理员、编辑等)。

我需要在Symfony2应用程序中利用这个数据库。 我的资源看起来像这样:ARTICLE_EDIT、ARTICLE_WRITE、COMMENT_EDIT等。

我的User实体在Symfony中实现了Symfony\Component\Security\Core\User\UserInterface接口,因此具有getRoles方法。

我打算使用这个方法来定义允许的资源,这意味着我将角色用作资源(我指在Zend Framework中称为资源的内容在这里称为角色)。

您确认我应该使用这个方法吗?

这意味着我不再关心每个用户的角色(管理员、编辑等),而只关心它的资源。

然后我会在我的控制器中使用$this->get('security.context')->isGranted('ROLE_ARTICLE_WRITE')

这是正确的做法吗?这样做是否绕了一个弯来使用Symfony中的角色?

2个回答

2

几年后回答这个问题,解决起来非常容易。

解决方案是混合角色和资源的概念。

假设定义了一个role表,一个resource表和一个role_resource多对多关系。

用户存储在user表中。

以下是相应的Doctrine实体:

User:

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;

    // ...
}

现在的解决方法是按照以下方式实现UserInterfacegetRoles

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')

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接