获得用户角色

时间:2013-05-25 16:58:54

标签: symfony roles

我有实体用户(实现UserInterface,它与实体角色有很多关系(实现RoleInterface)。

我的项目在登录后需要ROLE_ADMIN,否则将返回AccessDenied错误。 此外,我在我的数据库的Role表中添加了一个ROLE_ADMIN角色,并在user_Roles(多对多)表中创建了一个与此Role有关系的User。

但是当我登录时,我总是得到AccessDenied错误。

当我将User中的getRoles()方法更改为return array('ROLE_ADMIN');时,它可以正常工作。

有什么想法吗?

此外,我必须在User中添加此方法,否则我无法在我的数据库中添加用户。

  public function setUserRoles($userRoles)
    {
        if ( is_array($userRoles) ) {
            $this->userRoles = $userRoles ;
        } else {
            $this->userRoles->clear() ;
            $this->userRoles->add($userRoles) ;
        }
        return $this;
    }

用户:

namespace Acme\AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\EquatableInterface;
/**
 * User
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class User implements UserInterface, \Serializable
{   



    /**
     * @ORM\ManyToMany(targetEntity="Role", inversedBy="users")
     * @ORM\JoinTable(name="user_roles")
     *
     */
    private $userRoles;


    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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


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

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

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

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

    public function __construct()
    {
        $this->isActive = true;
        $this->salt = md5(uniqid(null, true));
        $this->userRoles = new ArrayCollection();
    }

    /*
     * --Interface Methoden--
     */
    /**
     * @inheritDoc
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * @inheritDoc
     */
    public function getSalt()
    {
        return $this->salt;
    }

    /**
     * @inheritDoc
     */
    public function getPassword()
    {
        return $this->password;
    }

    /**
     * @inheritDoc
     */
    public function getRoles()
    {
        return $this->userRoles->toArray();

    }

    /**
     * @inheritDoc
     */
    public function eraseCredentials()
    {
    }

    /**
     * @see \Serializable::serialize()
     */
    public function serialize()
    {
        return serialize(array(
                $this->id,
        ));
    }

    /**
     * @see \Serializable::unserialize()
     */
    public function unserialize($serialized)
    {
        list (
                $this->id,
        ) = unserialize($serialized);
    }






    public function isEqualTo(UserInterface $user)
    {
        return $this->id === $user->getId();
    }

    /**
     * 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 salt
     *
     * @param string $salt
     * @return User
     */
    public function setSalt($salt)
    {
        $this->salt = $salt;

        return $this;
    }

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

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

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

        return $this;
    }

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



    public function setUserRoles($userRoles)
    {
        if ( is_array($userRoles) ) {
            $this->userRoles = $userRoles ;
        } else {
            $this->userRoles->clear() ;
            $this->userRoles->add($userRoles) ;
        }
        return $this;
    }

    /**
     * Add userRoles
     *
     * @param \Amce\AppBundle\Entity\Role $userRoles
     * @return User
     */
    public function addUserRole(\Acme\AppBundle\Entity\Role $userRoles)
    {
        $this->userRoles[] = $userRoles;

        return $this;
    }

    /**
     * Remove userRoles
     *
     * @param \Acme\AppBundle\Entity\Role $userRoles
     */
    public function removeUserRole(\Acme\AppBundle\Entity\Role $userRoles)
    {
        $this->userRoles->removeElement($userRoles);
    }

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

作用:

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

/**
 * Role
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class Role implements RoleInterface
{

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

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

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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


    /*
     * methods for RoleInterface
    */
    public function getRole()
    {
        $this->getName();
    }

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

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

        return $this;
    }

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

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

Security.yml

    jms_security_extra:
    secure_all_services: false
    expressions: true

security:
    encoders:
        Acme\AppBundle\Entity\User: sha512
        Symfony\Component\Security\Core\User\User: plaintext


    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

    providers:
        chain_providers:
            chain:
                providers: [main, in_memory]
        main:
            entity: { class: Acme\AppBundle\Entity\User, property: username }
        in_memory:
            memory:
                users:
                    user:  { password: userpass, roles: [ 'ROLE_USER' ] }
                    admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }

    firewalls:

        secured_area:
            pattern:    .*
            form_login: ~
            logout: ~
            anonymous: ~
            #http_basic:
            #    realm: "Secured Demo Area"

    #access_control:
        #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }

UserRepository:

namespace Acme\AppBundle\Entity;

use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\NoResultException;

class UserRepository extends EntityRepository implements UserProviderInterface
{
    public function loadUserByUsername($username)
    {
        $q = $this
            ->createQueryBuilder('u')
            ->select('u, r')
            ->leftJoin('u.userRoles', 'r')
            ->where('u.username = :username')
            ->setParameter('username', $username)
            ->getQuery();


        try {
            // The Query::getSingleResult() method throws an exception
            // if there is no record matching the criteria.
            $user = $q->getSingleResult();
        } catch (NoResultException $e) {
            $message = sprintf(
                'Unable to find an active admin AcmeUserBundle:User object identified by "%s".',
                $username
            );
            throw new UsernameNotFoundException($message, 0, $e);
        }

        return $user;
    }
...
}

测试:

public function testLoadUserByUsername()
{
    $users = $this->em
    ->getRepository('AcmeAppBundle:User')
    ->loadUserByUsername('admintest')
    ;
    $test = $users->getRoles();

    print $test[0];
    $this->assertCount(1, $users);
}

1 个答案:

答案 0 :(得分:4)

请确保 UserRepository 中的 loadUserByUsername()用户实体和用户> getRoles上正确加入相应角色( )(和Role实体上的Role-> getRole())返回正确的数组/字符串。

例如,您可以通过手动查询UserRepository :: loadUserByUsername()方法在TestController中对此进行测试,并检查角色是否存在。

下一种可能性是延迟加载问题。尝试:

/**
 * @ORM\ManyToMany(targetEntity="Role", inversedBy="users", fetch="EAGER")
 * @ORM\JoinTable(name="user_roles")
 *
 */
private $userRoles;

文件说:

从自定义实体提供程序检索用户时,提高性能并避免延迟加载组。

如果它不是您问题的解决方案,请发表评论,无论如何,通过急切加载来获取用户组或用户角色关系是一种很好的做法。

请务必在更改提取设置后清除缓存!

提示:

关于您的addRole方法......您很可能不希望多次向您的用户添加角色实体,但前提是它们尚未添加。最好这样写:

public function addRole(RoleInterface $role)
{
   if (!$this->roles->contains($role)) {
       $this->roles->add($role);
   }

    return $this;
}