Symfony 5.3 新身份验证不保留我的身份验证
Posted
技术标签:
【中文标题】Symfony 5.3 新身份验证不保留我的身份验证【英文标题】:Symfony 5.3 new authentication doesn't keep my authentication 【发布时间】:2021-12-23 19:29:23 【问题描述】:我正在尝试使用 Symfony 5.3 提出的新的身份验证器管理器。我遵循 Symfonycasts 的课程。我只是按照用户的习惯将 UserIdentifier 更改为“用户名”而不是“电子邮件”。
<?php
namespace App\Security;
use App\Entity\User;
use App\Repository\UserRepository;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CustomCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
class LoginFormAuthenticator extends AbstractAuthenticator
use TargetPathTrait;
private UserRepository $userRepository;
private RouterInterface $router;
public function __construct(UserRepository $userRepository, RouterInterface $router)
$this->userRepository = $userRepository;
$this->router = $router;
public function supports(Request $request): ?bool
return ($request->getPathInfo() === '/login' && $request->isMethod('POST'));
public function authenticate(Request $request): PassportInterface
$username = $request->request->get('_username');
$password = $request->request->get('_password');
return new Passport(
new UserBadge($username, function($userIdentifier)
$user = $this->userRepository->findOneBy(['username' => $userIdentifier]);
if (!$user)
throw new UserNotFoundException();
return $user;
),
new PasswordCredentials($password),
[
new CsrfTokenBadge(
'authenticate',
$request->request->get('_csrf_token')
),
new RememberMeBadge(),
]
);
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
return new RedirectResponse($this->router->generate('core_home'));
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
$request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
return new RedirectResponse(
$this->router->generate('login')
);
根据日志,认证成功:
Nov 11 10:22:24 |INFO | SECURI Authenticator successful! authenticator="App\\Security\\LoginFormAuthenticator" token="Symfony\\Component\\Security\\Http\\Authenticator\\Token\\PostAuthenticationToken":"PostAuthenticationToken(user=\"denis.picard48@orange.fr\", authenticated=true, roles=\"ROLE_SUPER_ADMIN, ROLE_USER\")"
Nov 11 10:22:24 |DEBUG| SECURI Clearing remember-me cookie. name="REMEMBERME"
Nov 11 10:22:24 |DEBUG| SECURI Remember-me was requested; setting cookie.
Nov 11 10:22:25 |DEBUG| SECURI The "App\Security\LoginFormAuthenticator" authenticator set the response. Any later authenticator will not be called authenticator="App\\Security\\LoginFormAuthenticator"
Nov 11 10:22:25 |DEBUG| SECURI Stored the security token in the session. key="_security_main"
身份验证后,系统将信息存储在会话中
Nov 11 10:22:25 |DEBUG| DOCTRI SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'
Nov 11 10:22:25 |DEBUG| DOCTRI SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'
Nov 11 10:22:25 |DEBUG| DOCTRI SELECT DATABASE()
Nov 11 10:22:25 |DEBUG| DOCTRI SELECT COLUMN_NAME AS Field, COLUMN_TYPE AS Type, IS_NULLABLE AS `Null`, COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS Extra, COLUMN_COMMENT AS Comment, CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS Collation FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'olymphys_odpf' AND TABLE_NAME = 'doctrine_migration_versions' ORDER BY ORDINAL_POSITION ASC
Nov 11 10:22:25 |DEBUG| DOCTRI SELECT DATABASE()
Nov 11 10:22:25 |DEBUG| DOCTRI SELECT DISTINCT k.`CONSTRAINT_NAME`, k.`COLUMN_NAME`, k.`REFERENCED_TABLE_NAME`, k.`REFERENCED_COLUMN_NAME` /*!50116 , c.update_rule, c.delete_rule */ FROM information_schema.key_column_usage k /*!50116 INNER JOIN information_schema.referential_constraints c ON c.constraint_name = k.constraint_name AND c.table_name = 'doctrine_migration_versions' */ WHERE k.table_name = 'doctrine_migration_versions' AND k.table_schema = 'olymphys_odpf' /*!50116 AND c.constraint_schema = 'olymphys_odpf' */ AND k.`REFERENCED_COLUMN_NAME` is not NULL
Nov 11 10:22:25 |DEBUG| DOCTRI SELECT DATABASE()
Nov 11 10:22:25 |DEBUG| DOCTRI SELECT NON_UNIQUE AS Non_Unique, INDEX_NAME AS Key_name, COLUMN_NAME AS Column_Name, SUB_PART AS Sub_Part, INDEX_TYPE AS Index_Type FROM information_schema.STATISTICS WHERE TABLE_NAME = 'doctrine_migration_versions' AND TABLE_SCHEMA = 'olymphys_odpf' ORDER BY SEQ_IN_INDEX ASC
Nov 11 10:22:25 |DEBUG| DOCTRI SELECT ENGINE, AUTO_INCREMENT, TABLE_COLLATION, TABLE_COMMENT, CREATE_OPTIONS FROM information_schema.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'doctrine_migration_versions'
Nov 11 10:22:25 |DEBUG| DOCTRI SELECT * FROM doctrine_migration_versions
Nov 11 10:22:25 |DEBUG| DOCTRI SELECT DATABASE()
Nov 11 10:22:25 |DEBUG| PHP 127.0.0.1:40890 Closing
Nov 11 10:22:25 |INFO | SERVER POST (302) /login host="127.0.0.1:8004" ip="127.0.0.1" scheme="https"
Nov 11 10:22:25 |DEBUG| PHP 127.0.0.1:40894 Accepted path="/usr/bin/php7.4" php="7.4.7"
但是,这个成功的身份验证返回到我的路由 (core_home) 有效,我不再通过身份验证:
Nov 11 10:22:25 |INFO | REQUES Matched route "core_home". method="GET" request_uri="https://localhost:8000/" route="core_home" route_parameters="_controller":"App\\Controller\\CoreController::index","_route":"core_home"
Nov 11 10:22:25 |DEBUG| SECURI Checking for authenticator support. authenticators=2 firewall_name="main"
Nov 11 10:22:25 |DEBUG| SECURI Checking support on authenticator. authenticator="App\\Security\\LoginFormAuthenticator"
Nov 11 10:22:25 |DEBUG| SECURI Authenticator does not support the request.
Nov 11 10:22:25 |DEBUG| SECURI Checking support on authenticator. authenticator="Symfony\\Component\\Security\\Http\\Authenticator\\RememberMeAuthenticator"
Nov 11 10:22:25 |DEBUG| SECURI Remember-me cookie detected.
Nov 11 10:22:25 |INFO | PHP User Deprecated: Since symfony/http-kernel 5.3: "Symfony\Component\HttpKernel\Event\KernelEvent::isMasterRequest()" is deprecated, use "isMainRequest()" instead.
Nov 11 10:22:25 |DEBUG| SECURI Read existing security token from the session. key="_security_main" token_class="Symfony\\Component\\Security\\Http\\Authenticator\\Token\\PostAuthenticationToken"
Nov 11 10:22:25 |DEBUG| DOCTRI SELECT t0.id AS id_1, t0.username AS username_2, t0.roles AS roles_3, t0.password AS password_4, t0.email AS email_5, t0.is_active AS is_active_6, t0.token AS token_7, t0.password_requested_at AS password_requested_at_8, t0.rne AS rne_9, t0.nom AS nom_10, t0.prenom AS prenom_11, t0.adresse AS adresse_12, t0.ville AS ville_13, t0.code AS code_14, t0.phone AS phone_15, t0.createdAt AS createdAt_16, t0.updatedAt AS updatedAt_17, t0.lastVisit AS lastVisit_18, t0.civilite AS civilite_19, t0.centre_id AS centre_id_20, t0.autorisationphotos_id AS autorisationphotos_id_21, t0.rne_id_id AS rne_id_id_22 FROM user t0 WHERE t0.id = ? 0=1
Nov 11 10:22:25 |DEBUG| SECURI Cannot refresh token because user has changed. provider="Symfony\\Bridge\\Doctrine\\Security\\User\\EntityUserProvider" username="denis.picard48@orange.fr"
Nov 11 10:22:25 |DEBUG| SECURI Token was deauthenticated after trying to refresh it.
Nov 11 10:22:25 |DEBUG| SECURI Clearing remember-me cookie. name="REMEMBERME"
系统说我换了用户。但他这样做了!!
在 18h26 编辑:我的理解是,当身份验证器说 Authenticator 成功时,它会将我的电子邮件作为 UserIdentifier 而不是我的用户名存储在 PostAuthenticationToken 中(如我所愿)(请参阅日志的第一行,此处)。当它与数据进行比较时,它是错误的!而且用户变了……
有我的用户实体类:
<?php
namespace App\Entity;
use Doctrine\Common\Collections\Collection;
use App\Repository\UserRepository;
use Doctrine\Common\Proxy\Exception\InvalidArgumentException;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* /**
* @ORM\Entity(repositoryClass=UserRepository::class)
* @ORM\Table(name="user")
* @UniqueEntity(fields="email", message="Cet email est déjà enregistré en base.")
* @UniqueEntity(fields="username", message="Cet identifiant est déjà enregistré en base")
*/
class User implements UserInterface, PasswordAuthenticatedUserInterface, \Serializable
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=50, unique=true)
* @Assert\NotBlank()
* @Assert\Length(max=50)
*/
private $username;
/**
* @ORM\Column(type="array")
*/
private $roles;
/**
* @var string The hashed password
* @ORM\Column(type="string")
*/
private $password;
private $plainPassword;
/**
* @ORM\Column(type="string", length=180, unique=true)
* @Assert\NotBlank()
* @Assert\Length(max=60)
* @Assert\Email()
*/
private $email;
/**
* @ORM\Column(name="is_active", type="boolean", nullable=true)
*/
private $isActive;
/**
* @var string le token qui servira lors de l'oubli de mot de passe
* @ORM\Column(type="string", length=255, nullable=true)
*/
protected $token;
/**
* @ORM\Column(type="datetime", nullable=true)
* @var \DateTime
*/
private $passwordRequestedAt;
/**
* @var string
*
* @ORM\Column(name="rne", type="string", length=255, nullable=true)
*/
protected $rne;
/**
* @var string
*
* @ORM\Column(name="nom", type="string", length=255, nullable=true)
*/
protected $nom;
/**
* @var string
*
* @ORM\Column(name="prenom", type="string", length=255, nullable=true)
*/
protected $prenom;
/**
* @var string
*
* @ORM\Column(name="adresse", type="string", length=255, nullable=true)
*/
protected $adresse;
/**
* @var string
*
* @ORM\Column(name="ville", type="string", length=255, nullable=true)
*/
protected $ville;
/**
* @var string
*
* @ORM\Column(name="code", type="string", length=11, nullable=true)
*/
protected $code;
/**
* @var string
*
* @ORM\Column(name="phone", type="string", length=15, nullable=true)
*/
protected $phone;
/**
*
* @ORM\ManyToOne(targetEntity="App\Entity\Centrescia")
* @ORM\JoinColumn(name="centre_id", referencedColumnName="id" )
*/
private $centrecia;
/**
* @var \DateTime
*
* @ORM\Column(name="createdAt", type="datetime", nullable=true)
*/
private $createdAt;
/**
* @var \DateTime
*
* @ORM\Column(name="updatedAt", type="datetime", nullable=true)
*/
private $updatedAt;
/**
* @var \DateTime
*
* @ORM\Column(name="lastVisit", type="datetime", nullable=true)
*/
private $lastVisit;
/**
* @var string
*
* @ORM\Column(name="civilite", type="string", length=15, nullable=true)
*/
protected $civilite;
/**
*
* @ORM\OneToOne(targetEntity="App\Entity\Fichiersequipes", cascade="persist")
* @ORM\JoinColumn( referencedColumnName="id", )
*/
private $autorisationphotos;
/**
* @ORM\OneToMany(targetEntity=Equipes::class, mappedBy="hote")
*/
private $interlocuteur;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Rne")
*/
private $rneId;
public function __toString(): ?string
return $this->prenom.' '.$this->getNom();
public function __construct()
$this->isActive = true;
$this->roles = ['ROLE_USER'];
public function getId(): ?int
return $this->id;
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUsername(): string
return (string) $this->username;
public function setUsername(string $username): self
$this->username = $username;
return $this;
/**
* The public representation of the user (e.g. a username, an email address, etc.)
*
* @see UserInterface
*/
public function getUserIdentifier(): string
return (string) $this->email;
/*
* Get email
*/
public function getCentrecia()
return $this->centrecia;
/*
* Set CentreCia
*/
public function setCentrecia($centrecia): User
$this->centrecia= $centrecia;
return $this;
/*
* Get email
*/
public function getEmail()
return $this->email;
/*
* Set email
*/
public function setEmail($email)
$this->email = $email;
return $this;
/**
* @return string
*/
public function getToken(): string
return $this->token;
/**
* @param string $token
*/
public function setToken(?string $token): void
$this->token = $token;
/**
* @see UserInterface
*/
public function getRoles(): array
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
public function setRoles(array $roles): self
if (!in_array('ROLE_USER', $roles))
$roles[] = 'ROLE_USER';
foreach ($roles as $role)
if(substr($role, 0, 5) !== 'ROLE_')
throw new InvalidArgumentException("Chaque rôle doit commencer par 'ROLE_'");
$this->roles = $roles;
return $this;
/**
* @see PasswordAuthenticatedUserInterface
*/
public function getPassword(): string
return $this->password;
public function setPassword(string $password): self
$this->password = $password;
return $this;
/*
* Get isActive
*/
public function getIsActive()
return $this->isActive;
/*
* Set isActive
*/
public function setIsActive($isActive)
$this->isActive = $isActive;
return $this;
/**
* @see UserInterface
*/
public function getSalt()
// not needed when using the "bcrypt" algorithm in security.yaml
/**
* @see UserInterface
*/
public function eraseCredentials()
// If you store any temporary, sensitive data on the user, clear it here
$this->plainPassword = null;
/*
* Get passwordRequestedAt
*/
public function getPasswordRequestedAt()
return $this->passwordRequestedAt;
/*
* Set passwordRequestedAt
*/
public function setPasswordRequestedAt($passwordRequestedAt)
$this->passwordRequestedAt = $passwordRequestedAt;
return $this;
/** @see \Serializable::serialize() */
public function serialize()
return serialize(array(
$this->id,
$this->username,
$this->password,
$this->isActive,
// voir remarques sur salt plus haut
// $this->salt,
));
/** @see \Serializable::unserialize() */
public function unserialize($serialized)
list (
$this->id,
$this->username,
$this->password,
$this->isActive,
// voir remarques sur salt plus haut
// $this->salt
) = unserialize($serialized);
/**
* @Assert\NotBlank(groups="registration")
* @Assert\Length(max=4096)
*/
public function getPlainPassword(): ?string
return $this->plainPassword;
public function setPlainPassword(string $plainPassword): self
$this->plainPassword = $plainPassword;
return $this;
/**
* Set rne
*
* @param string $rne
*
* @return User
*/
public function setRne( $rne)
$this->rne= $rne;
return $this;
/**
* Get Adresse
*
* @return string
*/
public function getAdresse()
return $this->adresse;
/**
* Set adresse
*
* @param string $adresse
*
* @return User
*/
public function setAdresse( $adresse)
$this->adresse= $adresse;
return $this;
/**
* Get ville
*
* @return string
*/
public function getVille()
return $this->ville;
/**
* Set ville
*
* @param string $ville
*
* @return User
*/
public function setVille( $ville)
$this->ville= $ville;
return $this;
/**
* Get code
*
* @return string
*/
public function getCode()
return $this->code;
/**
* Set Code
*
* @param string $code
*
* @return User
*/
public function setCode( $code)
$this->code= $code;
return $this;
/**
* Get
*
* @return string
*/
public function getCivilite()
return $this->civilite;
/**
* Set civilite
*
* @param string $civilite
*
* @return User
*/
public function setCivilite( $civilite)
$this->civilite= $civilite;
return $this;
/**
* Get phone
*
* @return string
*/
public function getPhone()
return $this->phone;
/**
* Set phone
*
* @param string $code
*
* @return User
*/
public function setPhone( $phone)
$this->phone= $phone;
return $this;
/**
* Get rne
*
* @return string
*/
public function getRne()
return $this->rne;
/**
* Get nom
*
* @return string
*/
public function getNom()
return $this->nom;
/**
* Set nom
*
* @param string $nom
*
* @return User
*/
public function setNom( $nom)
$this->nom= $nom;
return $this;
/**
* Get prenom
*
* @return string
*/
public function getPrenom()
return $this->prenom;
/**
* Set prenom
*
* @param string $prenom
*
* @return User
*/
public function setPrenom( $prenom)
$this->prenom= $prenom;
return $this;
/*
* Get createdAt
*/
public function getCreatedAt()
return $this->createdAt;
/*
* Set updatedAt
*/
public function setCreatedAt($createdAt)
$this->createdAt = $createdAt;
return $this;
/*
* Get updatedAt
*/
public function getUpdatedAt()
return $this->updatedAt;
/*
* Set updatedAt
*/
public function setUpdatedAt($updatedAt)
$this->updatedAt =$updatedAt;
return $this;
/* Get lastVisit
*/
public function getLastVisit()
return $this->lastVisit;
/*
* Set lastVisit
*/
public function setLastVisit($lastVisit)
$this->lastVisit = $lastVisit;
return $this;
public function getAutorisationphotos()
return $this->autorisationphotos;
public function setAutorisationphotos($autorisation)
$this->autorisationphotos = $autorisation;
return $this;
public function getNomPrenom()
return $this->nom.' '.$this->prenom;
public function getPrenomNom()
return $this->prenom.' '.$this->nom;
/**
* @return Collection|Equipes[]
*/
public function getInterlocuteur(): Collection
return $this->interlocuteur;
public function addInterlocuteur(Equipes $interlocuteur): self
if (!$this->interlocuteur->contains($interlocuteur))
$this->interlocuteur[] = $interlocuteur;
$interlocuteur->setHote($this);
return $this;
public function removeInterlocuteur(Equipes $interlocuteur): self
if ($this->interlocuteur->removeElement($interlocuteur))
// set the owning side to null (unless already changed)
if ($interlocuteur->getHote() === $this)
$interlocuteur->setHote(null);
return $this;
public function getRneId(): ?rne
return $this->rneId;
public function setRneId(?rne $rneId): self
$this->rneId = $rneId;
return $this;
【问题讨论】:
你能显示你的用户实体类吗? @PatrickKenekayoro:谢谢!我的错误出现在用户身份中:我忘记了 getUserIdentifier:return (string) $this->email;而不是用户名!现在一切正常!!! 【参考方案1】:就像我在回答 Patrickkenekayoro 评论时所说的那样,我忘记了 User
实体的更改:getUserIdentifier()
函数应该带回 username
,而不是 email
。
【讨论】:
以上是关于Symfony 5.3 新身份验证不保留我的身份验证的主要内容,如果未能解决你的问题,请参考以下文章