我对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中使用角色不是一种规避的方法吗?
多年以后再回答这个问题,其实很容易解决。
解决方案是混合角色和资源的概念。
我们假设定义了一个role表、一个resource表和role_resource多对多关系。
用户存储在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;
// ...
}
Run Code Online (Sandbox Code Playgroud)
角色:
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;
// ...
}
Run Code Online (Sandbox Code Playgroud)
资源:
class Resource
{
/**
* @Id @Column(type="integer")
* @GeneratedValue
*/
private $id;
/** @Column(type="string") */
private $name;
// ...
}
Run Code Online (Sandbox Code Playgroud)
所以现在的解决方案是实现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;
}
}
Run Code Online (Sandbox Code Playgroud)
这样,可以通过这种方式检查归属于当前用户的资源(考虑有一个名为 的资源ARTICLE_WRITE):
$this->get('security.context')->isGranted('ROLE_ARTICLE_WRITE')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1080 次 |
| 最近记录: |