【问题标题】:getRole() form RoleInterface returns empty on symfonygetRole() form RoleInterface 在 symfony 上返回空
【发布时间】:2017-04-04 19:45:23
【问题描述】:

我在 symfony 上实现 JWT 令牌时遇到了一个大问题。 我已经使用 JWT 令牌,但我还需要将用户角色添加到令牌信息中。我正在使用侦听器 (JWTCreatedListener) 执行此操作:

public function onJWTCreated(JWTCreatedEvent $event)
{
    $request = $this->requestStack->getCurrentRequest();

    $payload       = $event->getData();
    $payload['ip'] = $request->getClientIp();
    $payload['roles'] = $event->getUser()->getRoles();

    $event->setData($payload);
}

我以这种方式实现了Role.php(AppBundle/Entity/Role.php):

<?php

namespace AppBundle\Entity;

use Symfony\Component\Security\Core\Role\RoleInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="acme_role")
 * @ORM\Entity()
 */
class Role implements RoleInterface
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(name="name", type="string", length=30)
     */
    private $name;

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

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

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

    /**
     * @see RoleInterface
     */
    public function getRole()
    {
        return $this->role;
    }

    // ... getters and setters for each property

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Role
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set role
     *
     * @param string $role
     *
     * @return Role
     */
    public function setRole($role)
    {
        $this->role = $role;

        return $this;
    }

    /**
     * Add user
     *
     * @param \AppBundle\Entity\User $user
     *
     * @return Role
     */
    public function addUser(\AppBundle\Entity\User $user)
    {
        $this->users[] = $user;

        return $this;
    }

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

    /**
     * Get users
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getUsers()
    {
        return $this->users;
    }
}

还有我的用户类:

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Table(name="users")
 * @ORM\Entity
 */
class User implements AdvancedUserInterface, \Serializable
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=25, unique=true)
     */
    private $username;

    /**
     * @ORM\Column(type="string", length=500)
     */
    private $password;

    /**
     * @ORM\Column(name="is_active", type="boolean")
     */
    private $isActive;

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

    public function __construct($username)
    {
        $this->isActive = true;
        $this->username = $username;
        $this->roles = new ArrayCollection();
    }

    public function getUsername()
    {
        return $this->username;
    }

    public function getSalt()
    {
        return null;
    }

    public function getPassword()
    {
        return $this->password;
    }

    public function setPassword($password)
    {
        $this->password = $password;
    }

    public function getRoles()
    {
         return $this->roles->toArray();
    }

    public function eraseCredentials()
    {
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set username
     *
     * @param string $username
     *
     * @return User
     */
    public function setUsername($username)
    {
        $this->username = $username;

        return $this;
    }

    /**
     * Set isActive
     *
     * @param boolean $isActive
     *
     * @return User
     */
    public function setIsActive($isActive)
    {
        $this->isActive = $isActive;

        return $this;
    }

    /**
     * Get isActive
     *
     * @return boolean
     */
    public function getIsActive()
    {
        return $this->isActive;
    }

    /**
     * Add role
     *
     * @param \AppBundle\Entity\Role $role
     *
     * @return User
     */
    public function addRole(\AppBundle\Entity\Role $role)
    {
        $this->roles[] = $role;

        return $this;
    }

    /**
     * Remove role
     *
     * @param \AppBundle\Entity\Role $role
     */
    public function removeRole(\AppBundle\Entity\Role $role)
    {
        $this->roles->removeElement($role);
    }

    public function isAccountNonExpired()
    {
        return true;
    }

    public function isAccountNonLocked()
    {
        return true;
    }

    public function isCredentialsNonExpired()
    {
        return true;
    }

    public function isEnabled()
    {
        return $this->isActive;
    }

    // serialize and unserialize must be updated - see below
    public function serialize()
    {
        return serialize(array(
            // ...
            $this->isActive
        ));
    }
    public function unserialize($serialized)
    {
        list (
            // ...
            $this->isActive
        ) = unserialize($serialized);
    }
}

问题是getRole()这个方法总是返回空。

这是我的数据库数据:

[users]
    id  username  password                                           is_active
    1  abriceno  $2y$13$NW6uNOKJGUQTSXirej4HKOwIa6mWzYqFxzz1ppWQjyp... 1

[acme_role]
id  name    role
1   admin   ROLE_ADMIN

[user_role]
user_id user_role
1        1

另外,我尝试使用教义从控制器测试中调用数据:

public function indexAction(Request $request)
    {

       $repository = $this->getDoctrine()->getRepository('AppBundle:User');
        $user = $repository->findOneByusername('abriceno');


        $username = $user->getUsername();
        $roles = $user->getRoles();

        $arr = array(
            'username' => $user->getUsername(),
            'password' => $user->getPassword(),
            'roles' => $user->getRoles()
        );
       return new JsonResponse($arr);

返回:

{"username":"abriceno","password":"$2y$13$NW6uNOKJGUQTSXirej4HKOwIa6mWzYqFxzz1ppWQjypQJLIgUGJ.m","roles":[{}]}

我很绝望...感谢您提供给我的所有帮助。

更新 1

如果我执行 print_r($role) 这将打印一个 huuuuuge 值列表:

array(1) { [0]=> object(AppBundle\Entity\Role)#624 (4) { ["id":"AppBundle\Entity\Role":private]=> int(1) ["name":"AppBundle\Entity\Role":private]=> string(5) "admin" ["role":"AppBundle\Entity\Role":private]=> string(10) "ROLE_ADMIN" ["users":"AppBundle\Entity\Role":private]=> object(Doctrine\ORM\PersistentCollection)#626 (9) { ["snapshot":"Doctrine\ORM\PersistentCollection":private]=> array(0) { } ["owner":"Doctrine\ORM\PersistentCollection":private]=> *RECURSION* 

...而且继续...很奇怪!

【问题讨论】:

    标签: php symfony jwt user-roles


    【解决方案1】:

    似乎连接表不是由学说直接处理的,因此您需要在学说中指定如何使用 JoinTable 注释映射引用的字段(参见default mapping 部分。)

    在你的情况下,尝试修改User实体中的roles relation定义如下:

    /**
     * @ORM\ManyToMany(targetEntity="Role", inversedBy="users")
     * @ORM\JoinTable(name="user_role",
     *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="user_role", referencedColumnName="id")})
     *
     */
    private $roles;
    

    希望有帮助

    【讨论】:

    • 谢谢@Matteo 我会试试这个!
    • 嗨@AliBriceño 告诉我,检查是否学说创建了一个名称为 Acme_User_Role 的表(您可以在生成的表的约束中检查)
    • 嗨@Matteo 我的朋友也有同样的问题。即使我删除所有这些表并执行命令php bin/console doctrine:schema:update --forceadn 仍然返回空:(
    • 我检查了 MySQL 上的约束并创建了 2 个
    • 顺便说一句...当我尝试使用它时:inverseJoinColumns={@ORM\JoinColumn(name="user_role", referencedColumnName="id")}) symfony 给我一个错误:[Doctrine\DBAL\Schema\SchemaException] There is no column with name 'user_role' on table 'user_role'. 所以我将其更改为 inverseJoinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id")}) 并且结果相同
    【解决方案2】:

    最后我用这段代码解决了这个问题:

            // Work of roles
        $roles = $event->getUser()->getRoles();
        $role_length = count($roles); 
        $role_list = array();
        for ($i=0; $i <$role_length ; $i++) { 
        array_push($role_list,$roles[$i]->getRole());
        }
    
    
        $payload       = $event->getData();
        $payload['ip'] = $request->getClientIp();
        $payload['roles'] = $role_list;
    

    问题(我猜)出在-&gt;getRoles(); 代码上。这将返回 Entity\Role 类的数组,而不是角色数组。

    现在转储是:

    {
      "token": "eyJhbGciOiJSUzI1NiJ9.....",
      "data": {
        "roles": [
          "ROLE_ADMIN"
        ]
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-03
      • 2019-05-15
      • 1970-01-01
      • 2014-06-09
      • 2015-02-04
      相关资源
      最近更新 更多