silex symfony:getRoles在登录时返回空列表

silex symfony:getRoles在登录时返回空列表,symfony,orm,doctrine,roles,silex,Symfony,Orm,Doctrine,Roles,Silex,你好,Silex(和Symfony)专家 我需要通过条令/ORM实现数据库身份验证用户/角色模型 这是我的silex composer设置: "require": { "silex/web-profiler": "^2.0", "monolog/monolog": "1.13.*", "symfony/twig-bridge": "^3.2", "symfony/monolog-bridge": "^3.2", "symfony/console": "^3

你好,Silex(和Symfony)专家

我需要通过条令/ORM实现数据库身份验证用户/角色模型

这是我的silex composer设置:

"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错误

我从这里开始(用户来自数据库,角色作为数组),并尝试扩展它,通过多对多关系从数据库中获取用户角色

有:

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;
    }

}
当用户注册时,他将获得该会话的角色_userrole, 身份验证和授权正常,并且在中创建了用户 数据库

然后我可以在控制器中为新用户分配新角色(“角色\u test1”、“角色\u test2”),多对多表myuser\u myrole被填充(myuser\u id myrole\u 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);
它抛出:

Argument 4 passed to Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken::__construct() must be of the type array, object given, 
好吧,也许有道理,因为$roles是一个Doctrine ArrayCollection

roles:
ArrayCollection {#388 ▼
  -elements: []
}
当我使用

// MyUser::getRoles() 
  return $this->roles;
// 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,有一些关于这方面的旧文档(管理数据库中的角色),但在symfony 3中它不起作用

在这里他们使用

   //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扩展EntityRepository{}类来执行查询并获取角色列表

(5) 我是否需要使用角色层次结构服务

(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);
}
试试这个:

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);
}

我在这件事上休息了一下,但现在它似乎起作用了。谢谢miikes的addRole()建议

最后我有:MyUser.php:

//Myuser.php
/**
 * MyUser
 *
 * @Entity 
 * @Table(name="myuser")
 */

class MyUser implements UserInterface,  \Serializable //, ObjectManagerAware
{
    ...

    /**
     * @ManyToMany(targetEntity="MyRole", inversedBy="users")
     */
    private $roles;

    public function __construct($email)
    {
    (...)
    $this->roles = new ArrayCollection();


     /**
     *
     * @return ArrayCollection list of the user's roles.
     */
    public function getRoles()
    {   
       $result = $this->roles->toArray();
       return $result;
    }

    public function assignToRole($role)
    {
        $this->roles[] = $role;
    }

    public function setRole($myrole)
    {   
    $this->roles= $myrole;
    }

    public function hasRole($role)
    {
        return in_array(strtoupper($role), $this->getRoles(), true);
    }

        public function addRole(MyRole $role)
    {
      $this->roles->add($role);
      //$role->users->addRole($this); // could not access roles->user->...  
                      // because private variable in MyRole but it works 
    }

        /**
     * Remove the given role from the user.
     *
     * @param string $role
     */
    public function removeRole($role)
    {   
      dump($role);
      $this->roles->removeElement($role);
    }

    (...) // other setters getters

    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->username,
            $this->password,
            $this->salt, 
        ));
    }

    /**
     * @see \Serializable::unserialize()
     */
    public function unserialize($serialized)
    {
        list (
            $this->id,
            $this->username,
            $this->password,
            $this->salt,
            ) = unserialize($serialized);
    }
}
和MyRole.php:

// MyRole.php

/**
 * MyRole
 * 
 * @Entity
 * @Table(name="myrole")
 */
class MyRole implements RoleInterface
{
    (...)

    /**
     * @ManyToMany(targetEntity="MyUser", mappedBy="roles")
     */
    private $users;


     /**
     * @var string
     * @Column(name="role", type="string", length=20, unique=true)
     */
    private $role;


    /*
    *  methods for RoleInterface
    *  @return string|null A string representation of the role, or null
    */
    public function getRole()
    {
       $result = $this->role;
       return ($result);
    }

    public function setRole($role)
    {
        $this->role= $role;
        return $this;
    }

    (...)

     /**
     * Constructor
     */
    public function __construct()
    {
        $this->users = new ArrayCollection();
    }

     /**
     * Add user
     * @param \MyEntities\MyUser $user
     * @return MyRole
     */
    public function addUser($user)
    {
        $this->users[] = $user;
        return $this;
    }


    public function setUser($user)
    {
        $this->users[] = $user;
        return $this;
    }

    /**
     * Remove user
     *
     * @param \MyEntities\MyUser $user
     */
    public function removeUser($user)
    {
        $this->users->removeElement($user);
    }

    /**
     * Get users
     *
     * @return ArrayCollection $users
     */
    public function getUsers()
    {
        return $this->users;
    }

     /**
     * __toString()
     *
     * @return string
     */
    public function __toString()
    {
        return $this->bezeichnung;
    }
}
在orm命令的帮助下

vendor/bin/doctrine  orm:validate-schema
vendor/bin/doctrine  orm:schema-tool:update  --dump-sql
生成了正确的多人表myuser\u myrole,角色设置在用户登录时起作用

我认为,最重要的是正确地使用函数addRole()(通过这个->角色->添加($role),而不是像这样->角色->添加角色($role))让doctrine在后台完成神奇的事情

谢谢你的帮助和评论!
德克

我在这件事上休息了一下,但现在它似乎起作用了。谢谢miikes的addRole()建议

最后我有:MyUser.php:

//Myuser.php
/**
 * MyUser
 *
 * @Entity 
 * @Table(name="myuser")
 */

class MyUser implements UserInterface,  \Serializable //, ObjectManagerAware
{
    ...

    /**
     * @ManyToMany(targetEntity="MyRole", inversedBy="users")
     */
    private $roles;

    public function __construct($email)
    {
    (...)
    $this->roles = new ArrayCollection();


     /**
     *
     * @return ArrayCollection list of the user's roles.
     */
    public function getRoles()
    {   
       $result = $this->roles->toArray();
       return $result;
    }

    public function assignToRole($role)
    {
        $this->roles[] = $role;
    }

    public function setRole($myrole)
    {   
    $this->roles= $myrole;
    }

    public function hasRole($role)
    {
        return in_array(strtoupper($role), $this->getRoles(), true);
    }

        public function addRole(MyRole $role)
    {
      $this->roles->add($role);
      //$role->users->addRole($this); // could not access roles->user->...  
                      // because private variable in MyRole but it works 
    }

        /**
     * Remove the given role from the user.
     *
     * @param string $role
     */
    public function removeRole($role)
    {   
      dump($role);
      $this->roles->removeElement($role);
    }

    (...) // other setters getters

    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->username,
            $this->password,
            $this->salt, 
        ));
    }

    /**
     * @see \Serializable::unserialize()
     */
    public function unserialize($serialized)
    {
        list (
            $this->id,
            $this->username,
            $this->password,
            $this->salt,
            ) = unserialize($serialized);
    }
}
和MyRole.php:

// MyRole.php

/**
 * MyRole
 * 
 * @Entity
 * @Table(name="myrole")
 */
class MyRole implements RoleInterface
{
    (...)

    /**
     * @ManyToMany(targetEntity="MyUser", mappedBy="roles")
     */
    private $users;


     /**
     * @var string
     * @Column(name="role", type="string", length=20, unique=true)
     */
    private $role;


    /*
    *  methods for RoleInterface
    *  @return string|null A string representation of the role, or null
    */
    public function getRole()
    {
       $result = $this->role;
       return ($result);
    }

    public function setRole($role)
    {
        $this->role= $role;
        return $this;
    }

    (...)

     /**
     * Constructor
     */
    public function __construct()
    {
        $this->users = new ArrayCollection();
    }

     /**
     * Add user
     * @param \MyEntities\MyUser $user
     * @return MyRole
     */
    public function addUser($user)
    {
        $this->users[] = $user;
        return $this;
    }


    public function setUser($user)
    {
        $this->users[] = $user;
        return $this;
    }

    /**
     * Remove user
     *
     * @param \MyEntities\MyUser $user
     */
    public function removeUser($user)
    {
        $this->users->removeElement($user);
    }

    /**
     * Get users
     *
     * @return ArrayCollection $users
     */
    public function getUsers()
    {
        return $this->users;
    }

     /**
     * __toString()
     *
     * @return string
     */
    public function __toString()
    {
        return $this->bezeichnung;
    }
}
在orm命令的帮助下

vendor/bin/doctrine  orm:validate-schema
vendor/bin/doctrine  orm:schema-tool:update  --dump-sql
生成了正确的多人表myuser\u myrole,角色设置在用户登录时起作用

我认为,最重要的是正确地使用函数addRole()(通过这个->角色->添加($role),而不是像这样->角色->添加角色($role))让doctrine在后台完成神奇的事情

谢谢你的帮助和评论!
德克

非常感谢,我尝试了两种建议。但没有更改,从getRoles()返回的数组仍然为空。我认为这种关系是正确的,因为我可以从MyUser控制器(实体类之外)访问角色。在执行登录操作时,实体中的MyUser::getRoles()会导致问题。也许我可以在登录时从其他地方访问entitymanager?您签入数据库表了吗?一切都正确吗?您还可以尝试检查多对一关系是否有效;如果我在MyUser.php中使用:公共函数getRoles(){$result=array($this->roles->getRole());return$result;}我在登录时得到了正确的角色,但这只是一个角色。你读过我的答案,关于保存许多关系的部分了吗?非常感谢,我尝试了这两个建议。但没有更改,从getRoles()返回的数组仍然为空。我认为这种关系是正确的,因为我可以从MyUser控制器(实体类之外)访问角色。在执行登录操作时,实体中的MyUser::getRoles()会导致问题。也许我可以在登录时从其他地方访问entitymanager?您签入数据库表了吗?一切都正确吗?您还可以尝试检查多对一关系是否有效。我尝试了多对一关系/***@ManyToOne(targetEntity=“MyRole”)*/