Symfony 5.3 新身份验证不保留我的身份验证



我正在尝试使用Symfony 5.3提出的新验证器管理器。我学习Symfonycasts的课程。我只是按照用户的习惯,将UserIdentifier改为"username"而不是"email"。

<?php
namespace AppSecurity;
use AppEntityUser;
use AppRepositoryUserRepository;
use SymfonyComponentHttpFoundationRedirectResponse;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentRoutingRouterInterface;
use SymfonyComponentSecurityCoreAuthenticationTokenTokenInterface;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentSecurityCoreExceptionAuthenticationException;
use SymfonyComponentSecurityCoreExceptionUserNotFoundException;
use SymfonyComponentSecurityCoreSecurity;
use SymfonyComponentSecurityHttpAuthenticatorAbstractAuthenticator;
use SymfonyComponentSecurityHttpAuthenticatorPassportBadgeCsrfTokenBadge;
use SymfonyComponentSecurityHttpAuthenticatorPassportBadgeRememberMeBadge;
use SymfonyComponentSecurityHttpAuthenticatorPassportBadgeUserBadge;
use SymfonyComponentSecurityHttpAuthenticatorPassportCredentialsCustomCredentials;
use SymfonyComponentSecurityHttpAuthenticatorPassportCredentialsPasswordCredentials;
use SymfonyComponentSecurityHttpAuthenticatorPassportPassport;
use SymfonyComponentSecurityHttpUtilTargetPathTrait;
use SymfonyComponentSecurityHttpAuthenticatorPassportPassportInterface;
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 "AppSecurityLoginFormAuthenticator" 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: "SymfonyComponentHttpKernelEventKernelEvent::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成功时,它会在PostAuthenticationToken中存储我的电子邮件作为UserIdentifier,而不是我的用户名(就像我想要的那样((请参阅日志的第一行(。当它将其与数据进行比较时,这是错误的!用户改变了。。。

有我的用户实体类:

<?php
namespace AppEntity;
use DoctrineCommonCollectionsCollection;
use AppRepositoryUserRepository;
use DoctrineCommonProxyExceptionInvalidArgumentException;
use DoctrineORMMapping as ORM;
use SymfonyComponentHttpFoundationSessionSessionInterface;
use SymfonyComponentSecurityCoreUserPasswordAuthenticatedUserInterface;
use SymfonyComponentValidatorConstraints as Assert;
use SymfonyBridgeDoctrineValidatorConstraintsUniqueEntity;
use SymfonyComponentSecurityCoreUserUserInterface;
use DoctrineCommonCollectionsArrayCollection;

/**
* /**
* @ORMEntity(repositoryClass=UserRepository::class)
* @ORMTable(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
{

/**
* @ORMId()
* @ORMGeneratedValue()
* @ORMColumn(type="integer")
*/
private $id;
/**
* @ORMColumn(type="string", length=50, unique=true)
* @AssertNotBlank()
* @AssertLength(max=50)
*/
private $username;
/**
* @ORMColumn(type="array")
*/
private $roles;
/**
* @var string The hashed password
* @ORMColumn(type="string")
*/
private $password;

private $plainPassword;
/**
* @ORMColumn(type="string", length=180, unique=true)
* @AssertNotBlank()
* @AssertLength(max=60)
* @AssertEmail()
*/
private $email;
/**
* @ORMColumn(name="is_active", type="boolean", nullable=true)
*/
private $isActive;
/**
* @var string le token qui servira lors de l'oubli de mot de passe
* @ORMColumn(type="string", length=255, nullable=true)
*/
protected $token;
/**
* @ORMColumn(type="datetime", nullable=true)
* @var DateTime
*/
private $passwordRequestedAt;
/**
* @var string
*
* @ORMColumn(name="rne", type="string", length=255, nullable=true)
*/
protected $rne;
/**
* @var string
*
* @ORMColumn(name="nom", type="string", length=255, nullable=true)
*/
protected $nom;

/**
* @var string
*
* @ORMColumn(name="prenom", type="string", length=255,                 nullable=true)
*/
protected $prenom;  
/**
* @var string
*
* @ORMColumn(name="adresse", type="string", length=255, nullable=true)
*/
protected $adresse;
/**
* @var string
*
* @ORMColumn(name="ville", type="string", length=255, nullable=true)
*/
protected $ville;
/**
* @var string
*
* @ORMColumn(name="code", type="string", length=11, nullable=true)
*/
protected $code;
/**
* @var string
*
* @ORMColumn(name="phone", type="string", length=15, nullable=true)
*/
protected $phone;
/**
*  
* @ORMManyToOne(targetEntity="AppEntityCentrescia")
* @ORMJoinColumn(name="centre_id",  referencedColumnName="id" )
*/       
private $centrecia;
/**
* @var DateTime
*
* @ORMColumn(name="createdAt", type="datetime", nullable=true)
*/
private $createdAt;
/**
* @var DateTime
*
* @ORMColumn(name="updatedAt", type="datetime", nullable=true)
*/
private $updatedAt;
/**
* @var DateTime
*
* @ORMColumn(name="lastVisit", type="datetime", nullable=true)
*/
private $lastVisit;
/**
* @var string
*
* @ORMColumn(name="civilite", type="string", length=15, nullable=true)
*/
protected $civilite;
/**
*  
* @ORMOneToOne(targetEntity="AppEntityFichiersequipes", cascade={"persist"})
* @ORMJoinColumn( referencedColumnName="id", )
*/
private $autorisationphotos;
/**
* @ORMOneToMany(targetEntity=Equipes::class, mappedBy="hote")
*/
private $interlocuteur;
/**
* @ORMManyToOne(targetEntity="AppEntityRne")
*/
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);
}
/**
* @AssertNotBlank(groups={"registration"})
* @AssertLength(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的评论时所说,我忘记了User实体中的一个更改:getUserIdentifier()函数应该返回username,而不是email

相关内容

最新更新