Я настроил брандмауэр для защиты части моего приложения (/manager). Я также настраиваю форму входа для аутентификации, но я зацикливаюсь на форме входа.
Я уверен, что пароль правильный, и после некоторого расследования я обнаружил, что аутентификация работает хорошо (я был аутентифицирован), но сразу после этого, когда symfony обновляет пользователя, он выходит из системы, потому что пользователь не тот. Я обнаружил, что это было вызвано несоответствием пароля. Проблема в том, что когда я вхожу в систему с помощью аутентификатора, пользователь сериализуется (я думаю, с TokenInterface), но поле «пароль» имеет значение null в TokenInterface (не в базе данных). Я использую JMSSerialiserBundle в своем приложении, я не знаю, возникает ли проблема. Можете вы помочь мне ?
Мой пользовательский класс
/**
* @ORM\Entity(repositoryClass = "App\Repository\UtilisateurRepository")
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name = "type", type = "string")
* @ORM\DiscriminatorMap({"eleve" = "Eleve", "gestionnaire" = "Gestionnaire"})
*/
abstract class Utilisateur implements UserInterface
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type = "integer")
* @Serializer\Groups({"id"})
*/
private $id;
/**
* @ORM\Column(type = "string", length=255)
* @Serializer\Groups({"Utilisateur"})
*/
private $nom;
/**
* @ORM\Column(type = "string", length=255)
* @Serializer\Groups({"Utilisateur"})
*/
private $prenom;
/**
* @ORM\Column(type = "string", length=255)
* @Serializer\Groups({"Utilisateur"})
*/
private $username;
/**
* @ORM\Column(type = "string", length=255)
* @Serializer\Exclude()
*/
private $password;
/**
* @ORM\Column(type = "string", length=1024, nullable=true)
* @Serializer\Groups({"Login"})
*/
private $token;
Мой класс аутентификатора
class ManagerAuthenticator extends AbstractFormLoginAuthenticator
{
use TargetPathTrait;
private $entityManager;
private $urlGenerator;
private $csrfTokenManager;
private $passwordEncoder;
public function __construct(
EntityManagerInterface $entityManager,
UrlGeneratorInterface $urlGenerator,
CsrfTokenManagerInterface $csrfTokenManager,
UserPasswordEncoderInterface $passwordEncoder
)
{
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
$this->passwordEncoder = $passwordEncoder;
}
public function supports(Request $request)
{
return 'app_login' === $request->attributes->get('_route')
&& $request->isMethod('POST');
}
public function getCredentials(Request $request)
{
$credentials = [
'username' => $request->request->get('username'),
'password' => $request->request->get('password'),
'csrf_token' => $request->request->get('_csrf_token'),
];
$request->getSession()->set(
Security::LAST_USERNAME,
$credentials['username']
);
return $credentials;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if (!$this->csrfTokenManager->isTokenValid($token)) {
throw new InvalidCsrfTokenException();
}
$user = $userProvider->loadUserByUsername($credentials['username']);
if (!$user) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('Username could not be found.');
}
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
return $this->passwordEncoder->isPasswordValid($user, $credentials['password'], $user->getSalt());
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
//On redirige sur la page précédente sauf si on vient du login
$targetPath = $this->getTargetPath($request->getSession(), $providerKey);
$loginRoute = $this->urlGenerator->generate('app_login');
if ($targetPath && strpos($loginRoute, $targetPath) === false) {
return new RedirectResponse($targetPath);
}
//Rediriger vers l'index
return new RedirectResponse($this->urlGenerator->generate('accueil_index'));
}
protected function getLoginUrl()
{
return $this->urlGenerator->generate('app_login');
}
}
Даже без @Serializer\Exclude() это не работает. Я не знаю, должен ли я переопределить какую-то функцию или реализовать интерфейс.




Проверьте Symfony\Component\Security\Core\Authentication\Token\AbstractToken::hasUserChanged()
Мой совет: создайте новый метод в вашем пользовательском классе с именем isEqualTo, и ваш класс должен реализовать EquatableInterface.
/**
* @param UserInterface $user
* @return bool
*/
public function isEqualTo(UserInterface $user): bool
{
return $this->username === $user->getUsername() && $this->id === $user->getId();
}
Также вам может понадобиться добавить эти два метода.
/**
* @see \Serializable::serialize()
*/
public function serialize(): string
{
return serialize([$this->id, $this->username,]);
}
/**
* @see \Serializable::unserialize()
* @param string $serialized
* @return User
*/
public function unserialize($serialized): self
{
[$this->id, $this->username] = unserialize($serialized);
return $this;
}
Не работает. На данный момент я использовал ваше решение, но если я выясню это, я обновлю ветку решением:/
Используя ваш метод, он работает, но я хотел бы следовать хорошей практике и проверять пароль. Я нашел ссылку, которая может мне помочь. Вечером протестирую и отпишусь. Ссылка : christophe-meneses.fr/article/…