为什么我的用户登录在升级到 Symfony3 后不再有效
Why is my User Login no longer working after upgrading to Symfony3
我遇到了 Symfony 3 的一个奇怪问题。
在 Symfony 2 下,一切都开箱即用(登录)。
但在 Symfony 3 下,它根本无法验证。
Doctrine 层未加载我的用户对象或存储库。
怎么回事?
好的,简短的更新。
我能够解决这个问题,并想分享发生的事情。
在调试完整的登录过程后,我偶然发现了无法登录的主要原因。
<?php
// src/AppBundle/Entity/UserRepository.php
namespace 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;
class UserRepository extends EntityRepository implements UserProviderInterface
{
public function loadUserByUsername($username)
{
$user = $this->createQueryBuilder('u')
->where('u.username = :username OR u.email = :email')
->setParameter('username', $username)
->setParameter('email', $username)
->getQuery()
->getOneOrNullResult();
if (null === $user) {
$message = sprintf(
'Unable to find an active admin AppBundle:User object identified by "%s".',
$username
);
throw new UsernameNotFoundException($message);
}
return $user;
}
public function refreshUser(UserInterface $user)
{
$class = get_class($user);
if (!$this->supportsClass($class)) {
throw new UnsupportedUserException(
sprintf(
'Instances of "%s" are not supported.',
$class
)
);
}
return $this->find($user->getId());
}
public function supportsClass($class)
{
return $this->getEntityName() === $class
|| is_subclass_of($class, $this->getEntityName());
}
}
好的,
这个 Repository Query Class 实际上是它不起作用的原因。
在调试和测试之后,我在 Class:
中找到了这个代码块
Symfony\Bridge\Doctrine\Security\User
/**
* {@inheritdoc}
*/
public function loadUserByUsername($username)
{
if (null !== $this->property) {
$user = $this->repository->findOneBy(array($this->property => $username));
} else {
if (!$this->repository instanceof UserLoaderInterface) {
throw new \InvalidArgumentException(sprintf('The Doctrine repository "%s" must implement Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface.', get_class($this->repository)));
}
$user = $this->repository->loadUserByUsername($username);
}
if (null === $user) {
throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
}
return $user;
}
它声明 Repository Class 必须是 UserLoaderInterface 的一个实例。
但是
的文档
http://symfony.com/doc/current/cookbook/security/entity_provider.html
声明它是 UserProviderInterface 的一个实例。
所以登录失败,因为它没有实现正确的接口。
文档(Cookbook)中有一个旧信息,或者 Symfony 团队只是忘记了它。 ^^(可能发生)
希望对大家有所帮助^^
UserProviderInterface 在 2.8 中更改为 UserLoaderInterface (see doc)
- class UserRepository 扩展了 EntityRepository 实现
UserProviderInterface
- class UserRepository 扩展了 EntityRepository
实现 UserLoaderInterface
这将解决问题,您也可以删除这些功能:
public 函数 refreshUser(UserInterface $user)
public 函数支持类($class)
对我来说,问题是 EquatableInterface 的 isEqualTo 方法(在我的用户实体上)在应该返回 true 时返回了 false。
我遇到了 Symfony 3 的一个奇怪问题。 在 Symfony 2 下,一切都开箱即用(登录)。 但在 Symfony 3 下,它根本无法验证。 Doctrine 层未加载我的用户对象或存储库。
怎么回事?
好的,简短的更新。 我能够解决这个问题,并想分享发生的事情。 在调试完整的登录过程后,我偶然发现了无法登录的主要原因。
<?php
// src/AppBundle/Entity/UserRepository.php
namespace 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;
class UserRepository extends EntityRepository implements UserProviderInterface
{
public function loadUserByUsername($username)
{
$user = $this->createQueryBuilder('u')
->where('u.username = :username OR u.email = :email')
->setParameter('username', $username)
->setParameter('email', $username)
->getQuery()
->getOneOrNullResult();
if (null === $user) {
$message = sprintf(
'Unable to find an active admin AppBundle:User object identified by "%s".',
$username
);
throw new UsernameNotFoundException($message);
}
return $user;
}
public function refreshUser(UserInterface $user)
{
$class = get_class($user);
if (!$this->supportsClass($class)) {
throw new UnsupportedUserException(
sprintf(
'Instances of "%s" are not supported.',
$class
)
);
}
return $this->find($user->getId());
}
public function supportsClass($class)
{
return $this->getEntityName() === $class
|| is_subclass_of($class, $this->getEntityName());
}
}
好的, 这个 Repository Query Class 实际上是它不起作用的原因。 在调试和测试之后,我在 Class:
中找到了这个代码块Symfony\Bridge\Doctrine\Security\User
/**
* {@inheritdoc}
*/
public function loadUserByUsername($username)
{
if (null !== $this->property) {
$user = $this->repository->findOneBy(array($this->property => $username));
} else {
if (!$this->repository instanceof UserLoaderInterface) {
throw new \InvalidArgumentException(sprintf('The Doctrine repository "%s" must implement Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface.', get_class($this->repository)));
}
$user = $this->repository->loadUserByUsername($username);
}
if (null === $user) {
throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
}
return $user;
}
它声明 Repository Class 必须是 UserLoaderInterface 的一个实例。 但是
的文档http://symfony.com/doc/current/cookbook/security/entity_provider.html
声明它是 UserProviderInterface 的一个实例。
所以登录失败,因为它没有实现正确的接口。 文档(Cookbook)中有一个旧信息,或者 Symfony 团队只是忘记了它。 ^^(可能发生)
希望对大家有所帮助^^
UserProviderInterface 在 2.8 中更改为 UserLoaderInterface (see doc)
- class UserRepository 扩展了 EntityRepository 实现
UserProviderInterface - class UserRepository 扩展了 EntityRepository 实现 UserLoaderInterface
这将解决问题,您也可以删除这些功能:
public 函数 refreshUser(UserInterface $user)public 函数支持类($class)
对我来说,问题是 EquatableInterface 的 isEqualTo 方法(在我的用户实体上)在应该返回 true 时返回了 false。