你好 Silex(和 Symfony)专家,
我需要通过 Doctrine /ORM 实现数据库身份验证用户/角色模型。
这是我的 silex 作曲家设置:
"require": {
"silex/web-profiler": "^2.0",
"monolog/monolog": "1.13.*",
"symfony/twig-bridge": "^3.2",
"symfony/monolog-bridge": "^3.2",
"symfony/console": "^3.2",
"symfony/yaml": "^3.2",
"symfony/security-bundle": "^3.2",
"doctrine/orm": "^2.5",
"dflydev/doctrine-orm-service-provider": "^2.0",
"symfony/form": "^3.2",
"symfony/validator": "^3.2",
"symfony/config": "^3.2",
"symfony/doctrine-bridge": "^3.2",
"doctrine/migrations": "^1.5"
},
用户可以注册。注册用户可以登录和注销。非注册访问者具有匿名角色。
symfony 分析器正在工作,所以我可以看到安全状态(身份验证/授权)。我还跟踪 apache 日志文件中的 php 错误。
我从这里开始https://github.com/fredjuvaux/silex-orm-user-provider(来自数据库的用户,作为数组的角色)并尝试扩展它以通过多对多关系学说从数据库中获取用户角色。
有:
class MyUserController (different user actions like user,edit, register,... )
class MyUserManager implements UserProviderInterface (loadUserByUsername, ...)
class MyUserServiceProvider implements ServiceProviderInterface, ControllerProviderInterface, BootableProviderInterface (controller routing and template setting)
ORM 实体是:
User:
/**
* MyUser
*
* @Entity
* @Table(name="myuser")
*/
class MyUser implements UserInterface, \Serializable
{
....
/**
* @ManyToMany(targetEntity="MyRole", inversedBy="users")
*
*/
private $roles;
...
* Constructor.
*
* @param string $email
*/
public function __construct($email)
{
$this->email = $email;
$this->created = time();
$this->salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
$this->roles = new ArrayCollection();
}
...
/**
*
* @return ArrayCollection list of the user's roles.
*/
public function getRoles()
{
$result = $this->roles->toArray(); // throws error for login:
// $result = $this->roles; // test // thhrows error : null object
dump($this->roles);
// $result = array("ROLE_USER", "ROLE_OTHER"); // static setting and
works for login
return $result;
}
...
}
Roles (implements Roleinterface)
/**
* MyRole
*
* @Entity
* @Table(name="myrole")
*/
class MyRole implements RoleInterface
{
/**
* @var string
* @Column(name="role", type="string", length=20, unique=true)
*/
private $role;
/**
* @ManyToMany(targetEntity="MyUser", mappedBy="roles")
*/
private $users;
...
/*
* methods for RoleInterface
* @return string|null A string representation of the role, or null
*/
public function getRole()
{
$result = $this->role;
return $result;
}
}
当用户注册时,他为该会话获得 ROLE_USER 角色,身份验证和授权正常,并且在数据库中创建了一个用户。
然后我可以在控制器中为新用户分配新角色(“role_test1”、“role_test2”),填充多对多表 myuser_myrole(myuser_id myrole_id)。当我更改角色时,实体管理器会正确更新它们。
当我从 userController 访问用户实体来处理它时,我可以访问分配的角色:
// MyUserController.php
$user = $em->getRepository('MyEntities\MyUser')->find($id);
$roles= $user->getRoles()
$role_length = count($roles);
$role_list = array();
for ($i=0; $i <$role_length ; $i++)
{
array_push($role_list,$roles[$i]->getRole()); // MyRole::getRole() prints out something to screen.
}
printf("<br> role-list:"); dump($role_list);
调用这个控制器会通过 MyRole::getRole() 打印出分配的角色,所以 ORM 访问在这里工作。
现在奇怪了:
我想用登录表单登录新用户。
当我使用
// MyUser::getRoles()
return $this->roles;
它抛出:
Argument 4 passed to Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken::__construct() must be of the type array, object given,
好吧,也许是有道理的,因为 $roles 是一个 Doctrine ArrayCollection。
当我使用
// MyUser::getRoles()
return $this->roles->toArray();
我可以使用用户密码登录,但未通过身份验证(黄色状态)。转储角色后,我收到一个空数组 ArrayCollection。
roles:
ArrayCollection {#388 ▼
-elements: []
}
UsernamePasswordToken 有一个空的角色数组。
When I use
// MyUser::getRoles()
return array("ROLE_HELLO1", "ROLE_HELLO2"); // static role array with strings
我可以登录并使用以下角色进行身份验证:
角色
array:2 [▼
0 => "ROLE_HELLO1"
1 => "ROLE_HELLO2"
]
有关于 symfony 2 http://symfony.com/doc/2.0/cookbook/security/entity_provider.html 的旧文档(管理数据库中的角色),但它在 symfony3 中不起作用。
他们在这里使用
//class User
public function getRoles()
{
return $this->groups->toArray();
}
//class Group extends Role (not RoleInterface, old?)
public function getRole()
{
return $this->role;
}
用于用户管理的实际 symfony 文档没有展示如何使用存储在数据库中的角色。
总之:
登录名和用户/角色无法按预期工作:
MyUser::getRoles()
不通过学说 ORM 从数据库接收角色。
必须返回用于登录的角色字符串数组。
在另一个控制器中提供正确的角色关联。
问题:
(1) 这是 Silex 特有的问题吗?
(2) 如何正确使用它或解决方法的好链接/文档在哪里?
(3) LoadUserByUsername() 方法是否会干扰所有这些?
(4) 是否需要类 MyUserRepository extends EntityRepository {} 来执行查询并获取角色列表?
(5) 是否需要使用Role Hierarchy服务?
(6) “用户”和“角色”是否有特殊的命名约定(表名或类名)?
我发现许多帖子要求相同/相似,但它们在这里没有帮助。
谢谢你的帮助,我真的很坚持!
短剑
试试这个:
public function getRoles()
{
return $this->roles->map(function (MyRole $role) {
return $role->getRole();
})->toArray();
}
您还应该检查关系是否正确保存在数据库中。如果MyUser和MyRole之间存在ManyToMany关系,则必须确保该关系保存在两个实体中。
//class MyUser
public function addRole(MyRole $role)
{
$this-roles->add($role);
$role->users->add($user);
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句