我有实体用户(实现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);
}
答案 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;
}