Intereting Posts

Symfony & Guard: «Токен безопасности был удален из-за исключения AccountStatusException»

Я попытался создать аутентификатор для моей формы входа, но я всегда нелюбован по какой-то непонятной причине.

[2016-10-05 18:54:53] security.INFO: Guard authentication successful! {"token":"[object] (Symfony\\Component\\Security\\Guard\\Token\\PostAuthenticationGuardToken: PostAuthenticationGuardToken(user=\"test@test.test\", authenticated=true, roles=\"ROLE_USER\"))","authenticator":"AppBundle\\Security\\Authenticator\\FormLoginAuthenticator"} [] [2016-10-05 18:54:54] security.INFO: An AuthenticationException was thrown; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AuthenticationExpiredException(code: 0): at /space/products/insurance/vendor/symfony/symfony/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php:86)"} [] [2016-10-05 18:54:54] security.INFO: The security token was removed due to an AccountStatusException. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AuthenticationExpiredException(code: 0): at /space/products/insurance/vendor/symfony/symfony/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php:86)"} [] 

Я не понимаю этого «АутентификацияExpiredException», поскольку у меня нет ни одного апатрида, ни какого-либо истечения в любом случае в моем приложении.

Означает ли этот вопрос никому?


Редактировать 1

После нескольких часов, похоже, что я не зарегистрирован из-за {{ is_granted('ROLE_USER') }} в Twig. Не понимаю, почему так или иначе.

Изменить 2

Если я дам () мой токен безопасности в методе аутентификатора onAuthenticationSuccess, authenticated = true .

Но, если я сброшу () мой токен безопасности после перенаправления или при доступе к новой странице, 'authenticated' = false .

Почему, черт возьми, моя аутентификация не сохраняется.


приложение / Config / security.yml

 security: encoders: AppBundle\Security\User\Member: algorithm: bcrypt cost: 12 providers: members: id: app.provider.member role_hierarchy: ROLE_ADMIN: "ROLE_USER" firewalls: dev: pattern: "^/(_(profiler|wdt|error)|css|images|js)/" security: false main: pattern: "^/" anonymous: ~ logout: ~ guard: authenticators: - app.authenticator.form_login access_control: - { path: "^/connect", role: "IS_AUTHENTICATED_ANONYMOUSLY" } - { path: "^/register", role: "IS_AUTHENTICATED_ANONYMOUSLY" } - { path: "^/admin", role: "ROLE_ADMIN" } - { path: "^/user", role: "ROLE_USER" } - { path: "^/logout", role: "ROLE_USER" } 

AppBundle / Controller / SecurityController.php

 <?php namespace AppBundle\Controller; use AppBundle\Base\BaseController; use AppBundle\Form\Type\ConnectType; use AppBundle\Security\User\Member; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; use Symfony\Component\HttpFoundation\Request; class SecurityController extends BaseController { /** * @Route("/connect", name="security_connect") * @Template() */ public function connectAction(Request $request) { $connectForm = $this ->createForm(ConnectType::class) ->handleRequest($request) ; return [ 'connect' => $connectForm->createView(), ]; } } 

AppBundle / Форма / тип / ConnectType.php

 <?php namespace AppBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Validator\Constraints; use EWZ\Bundle\RecaptchaBundle\Form\Type\EWZRecaptchaType; use EWZ\Bundle\RecaptchaBundle\Validator\Constraints\IsTrue as RecaptchaTrue; class ConnectType extends AbstractType { /** * @param FormBuilderInterface $builder * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('email', Type\EmailType::class, [ 'label' => 'Your email', 'required' => true, 'constraints' => [ new Constraints\Length(['min' => 8]) ], ]) ->add('password', Type\PasswordType::class, [ 'label' => 'Your password', 'constraints' => new Constraints\Length(['min' => 8, 'max' => 4096]), /* CVE-2013-5750 */ ]) ->add('recaptcha', EWZRecaptchaType::class, [ 'label' => 'Please tick the checkbox below', 'constraints' => [ new RecaptchaTrue() ], ]) ->add('submit', Type\SubmitType::class, [ 'label' => 'Connect', ]) ; } } 

AppBundle / Безопасность / Authenticator / FormLoginAuthenticator.php

 <?php namespace AppBundle\Security\Authenticator; use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use AppBundle\Form\Type\ConnectType; class FormLoginAuthenticator extends AbstractFormLoginAuthenticator { private $container; // ¯\_(ツ)_/¯ public function __construct(ContainerInterface $container) { $this->container = $container; } public function getCredentials(Request $request) { if ($request->getPathInfo() !== '/connect') { return null; } $connectForm = $this ->container ->get('form.factory') ->create(ConnectType::class) ->handleRequest($request) ; if ($connectForm->isValid()) { $data = $connectForm->getData(); return [ 'username' => $data['email'], 'password' => $data['password'], ]; } return null; } public function getUser($credentials, UserProviderInterface $userProvider) { return $userProvider->loadUserByUsername($credentials['username']); } public function checkCredentials($credentials, UserInterface $user) { $isValid = $this ->container ->get('security.password_encoder') ->isPasswordValid($user, $credentials['password']) ; if (!$isValid) { throw new BadCredentialsException(); } return true; } protected function getLoginUrl() { return $this ->container ->get('router') ->generate('security_connect') ; } protected function getDefaultSuccessRedirectUrl() { return $this ->container ->get('router') ->generate('home') ; } } 

AppBundle / Безопасность / Поставщик / MemberProvider.php

 <?php namespace AppBundle\Security\Provider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use AppBundle\Security\User\Member; use Api\Gateway\RequestResponse\RequestResponseHandlerInterface; use Api\Business\InsuranceWebsite\Action\GetInsuranceMember\GetInsuranceMemberRequest; use Api\Gateway\Exception\NoResultException; class MemberProvider implements UserProviderInterface { protected $gateway; public function __construct(RequestResponseHandlerInterface $gateway) { $this->gateway = $gateway; } public function loadUserByUsername($username) { try { $response = $this->gateway->handle( new GetInsuranceMemberRequest($username) ); } catch (NoResultException $ex) { throw new UsernameNotFoundException( sprintf('Username "%s" does not exist.', $username) ); } $member = new Member(); $member->setId($response->getId()); $member->setUsername($response->getEmail()); $member->setPassword($response->getPassword()); $member->setCompanyId($response->getCompanyId()); $member->setFirstname($response->getFirstname()); $member->setLastname($response->getLastname()); $member->setIsManager($response->isManager()); $member->setIsEnabled($response->isEnabled()); return $member; } public function refreshUser(UserInterface $user) { if (!$user instanceof Member) { throw new UnsupportedUserException( sprintf('Instances of "%s" are not supported.', get_class($user)) ); } return $this->loadUserByUsername($user->getUsername()); } public function supportsClass($class) { return $class === Member::class; } } как <?php namespace AppBundle\Security\Provider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use AppBundle\Security\User\Member; use Api\Gateway\RequestResponse\RequestResponseHandlerInterface; use Api\Business\InsuranceWebsite\Action\GetInsuranceMember\GetInsuranceMemberRequest; use Api\Gateway\Exception\NoResultException; class MemberProvider implements UserProviderInterface { protected $gateway; public function __construct(RequestResponseHandlerInterface $gateway) { $this->gateway = $gateway; } public function loadUserByUsername($username) { try { $response = $this->gateway->handle( new GetInsuranceMemberRequest($username) ); } catch (NoResultException $ex) { throw new UsernameNotFoundException( sprintf('Username "%s" does not exist.', $username) ); } $member = new Member(); $member->setId($response->getId()); $member->setUsername($response->getEmail()); $member->setPassword($response->getPassword()); $member->setCompanyId($response->getCompanyId()); $member->setFirstname($response->getFirstname()); $member->setLastname($response->getLastname()); $member->setIsManager($response->isManager()); $member->setIsEnabled($response->isEnabled()); return $member; } public function refreshUser(UserInterface $user) { if (!$user instanceof Member) { throw new UnsupportedUserException( sprintf('Instances of "%s" are not supported.', get_class($user)) ); } return $this->loadUserByUsername($user->getUsername()); } public function supportsClass($class) { return $class === Member::class; } } как <?php namespace AppBundle\Security\Provider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use AppBundle\Security\User\Member; use Api\Gateway\RequestResponse\RequestResponseHandlerInterface; use Api\Business\InsuranceWebsite\Action\GetInsuranceMember\GetInsuranceMemberRequest; use Api\Gateway\Exception\NoResultException; class MemberProvider implements UserProviderInterface { protected $gateway; public function __construct(RequestResponseHandlerInterface $gateway) { $this->gateway = $gateway; } public function loadUserByUsername($username) { try { $response = $this->gateway->handle( new GetInsuranceMemberRequest($username) ); } catch (NoResultException $ex) { throw new UsernameNotFoundException( sprintf('Username "%s" does not exist.', $username) ); } $member = new Member(); $member->setId($response->getId()); $member->setUsername($response->getEmail()); $member->setPassword($response->getPassword()); $member->setCompanyId($response->getCompanyId()); $member->setFirstname($response->getFirstname()); $member->setLastname($response->getLastname()); $member->setIsManager($response->isManager()); $member->setIsEnabled($response->isEnabled()); return $member; } public function refreshUser(UserInterface $user) { if (!$user instanceof Member) { throw new UnsupportedUserException( sprintf('Instances of "%s" are not supported.', get_class($user)) ); } return $this->loadUserByUsername($user->getUsername()); } public function supportsClass($class) { return $class === Member::class; } } как <?php namespace AppBundle\Security\Provider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use AppBundle\Security\User\Member; use Api\Gateway\RequestResponse\RequestResponseHandlerInterface; use Api\Business\InsuranceWebsite\Action\GetInsuranceMember\GetInsuranceMemberRequest; use Api\Gateway\Exception\NoResultException; class MemberProvider implements UserProviderInterface { protected $gateway; public function __construct(RequestResponseHandlerInterface $gateway) { $this->gateway = $gateway; } public function loadUserByUsername($username) { try { $response = $this->gateway->handle( new GetInsuranceMemberRequest($username) ); } catch (NoResultException $ex) { throw new UsernameNotFoundException( sprintf('Username "%s" does not exist.', $username) ); } $member = new Member(); $member->setId($response->getId()); $member->setUsername($response->getEmail()); $member->setPassword($response->getPassword()); $member->setCompanyId($response->getCompanyId()); $member->setFirstname($response->getFirstname()); $member->setLastname($response->getLastname()); $member->setIsManager($response->isManager()); $member->setIsEnabled($response->isEnabled()); return $member; } public function refreshUser(UserInterface $user) { if (!$user instanceof Member) { throw new UnsupportedUserException( sprintf('Instances of "%s" are not supported.', get_class($user)) ); } return $this->loadUserByUsername($user->getUsername()); } public function supportsClass($class) { return $class === Member::class; } } как <?php namespace AppBundle\Security\Provider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use AppBundle\Security\User\Member; use Api\Gateway\RequestResponse\RequestResponseHandlerInterface; use Api\Business\InsuranceWebsite\Action\GetInsuranceMember\GetInsuranceMemberRequest; use Api\Gateway\Exception\NoResultException; class MemberProvider implements UserProviderInterface { protected $gateway; public function __construct(RequestResponseHandlerInterface $gateway) { $this->gateway = $gateway; } public function loadUserByUsername($username) { try { $response = $this->gateway->handle( new GetInsuranceMemberRequest($username) ); } catch (NoResultException $ex) { throw new UsernameNotFoundException( sprintf('Username "%s" does not exist.', $username) ); } $member = new Member(); $member->setId($response->getId()); $member->setUsername($response->getEmail()); $member->setPassword($response->getPassword()); $member->setCompanyId($response->getCompanyId()); $member->setFirstname($response->getFirstname()); $member->setLastname($response->getLastname()); $member->setIsManager($response->isManager()); $member->setIsEnabled($response->isEnabled()); return $member; } public function refreshUser(UserInterface $user) { if (!$user instanceof Member) { throw new UnsupportedUserException( sprintf('Instances of "%s" are not supported.', get_class($user)) ); } return $this->loadUserByUsername($user->getUsername()); } public function supportsClass($class) { return $class === Member::class; } } как <?php namespace AppBundle\Security\Provider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use AppBundle\Security\User\Member; use Api\Gateway\RequestResponse\RequestResponseHandlerInterface; use Api\Business\InsuranceWebsite\Action\GetInsuranceMember\GetInsuranceMemberRequest; use Api\Gateway\Exception\NoResultException; class MemberProvider implements UserProviderInterface { protected $gateway; public function __construct(RequestResponseHandlerInterface $gateway) { $this->gateway = $gateway; } public function loadUserByUsername($username) { try { $response = $this->gateway->handle( new GetInsuranceMemberRequest($username) ); } catch (NoResultException $ex) { throw new UsernameNotFoundException( sprintf('Username "%s" does not exist.', $username) ); } $member = new Member(); $member->setId($response->getId()); $member->setUsername($response->getEmail()); $member->setPassword($response->getPassword()); $member->setCompanyId($response->getCompanyId()); $member->setFirstname($response->getFirstname()); $member->setLastname($response->getLastname()); $member->setIsManager($response->isManager()); $member->setIsEnabled($response->isEnabled()); return $member; } public function refreshUser(UserInterface $user) { if (!$user instanceof Member) { throw new UnsupportedUserException( sprintf('Instances of "%s" are not supported.', get_class($user)) ); } return $this->loadUserByUsername($user->getUsername()); } public function supportsClass($class) { return $class === Member::class; } } как <?php namespace AppBundle\Security\Provider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use AppBundle\Security\User\Member; use Api\Gateway\RequestResponse\RequestResponseHandlerInterface; use Api\Business\InsuranceWebsite\Action\GetInsuranceMember\GetInsuranceMemberRequest; use Api\Gateway\Exception\NoResultException; class MemberProvider implements UserProviderInterface { protected $gateway; public function __construct(RequestResponseHandlerInterface $gateway) { $this->gateway = $gateway; } public function loadUserByUsername($username) { try { $response = $this->gateway->handle( new GetInsuranceMemberRequest($username) ); } catch (NoResultException $ex) { throw new UsernameNotFoundException( sprintf('Username "%s" does not exist.', $username) ); } $member = new Member(); $member->setId($response->getId()); $member->setUsername($response->getEmail()); $member->setPassword($response->getPassword()); $member->setCompanyId($response->getCompanyId()); $member->setFirstname($response->getFirstname()); $member->setLastname($response->getLastname()); $member->setIsManager($response->isManager()); $member->setIsEnabled($response->isEnabled()); return $member; } public function refreshUser(UserInterface $user) { if (!$user instanceof Member) { throw new UnsupportedUserException( sprintf('Instances of "%s" are not supported.', get_class($user)) ); } return $this->loadUserByUsername($user->getUsername()); } public function supportsClass($class) { return $class === Member::class; } } как <?php namespace AppBundle\Security\Provider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use AppBundle\Security\User\Member; use Api\Gateway\RequestResponse\RequestResponseHandlerInterface; use Api\Business\InsuranceWebsite\Action\GetInsuranceMember\GetInsuranceMemberRequest; use Api\Gateway\Exception\NoResultException; class MemberProvider implements UserProviderInterface { protected $gateway; public function __construct(RequestResponseHandlerInterface $gateway) { $this->gateway = $gateway; } public function loadUserByUsername($username) { try { $response = $this->gateway->handle( new GetInsuranceMemberRequest($username) ); } catch (NoResultException $ex) { throw new UsernameNotFoundException( sprintf('Username "%s" does not exist.', $username) ); } $member = new Member(); $member->setId($response->getId()); $member->setUsername($response->getEmail()); $member->setPassword($response->getPassword()); $member->setCompanyId($response->getCompanyId()); $member->setFirstname($response->getFirstname()); $member->setLastname($response->getLastname()); $member->setIsManager($response->isManager()); $member->setIsEnabled($response->isEnabled()); return $member; } public function refreshUser(UserInterface $user) { if (!$user instanceof Member) { throw new UnsupportedUserException( sprintf('Instances of "%s" are not supported.', get_class($user)) ); } return $this->loadUserByUsername($user->getUsername()); } public function supportsClass($class) { return $class === Member::class; } } как <?php namespace AppBundle\Security\Provider; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use AppBundle\Security\User\Member; use Api\Gateway\RequestResponse\RequestResponseHandlerInterface; use Api\Business\InsuranceWebsite\Action\GetInsuranceMember\GetInsuranceMemberRequest; use Api\Gateway\Exception\NoResultException; class MemberProvider implements UserProviderInterface { protected $gateway; public function __construct(RequestResponseHandlerInterface $gateway) { $this->gateway = $gateway; } public function loadUserByUsername($username) { try { $response = $this->gateway->handle( new GetInsuranceMemberRequest($username) ); } catch (NoResultException $ex) { throw new UsernameNotFoundException( sprintf('Username "%s" does not exist.', $username) ); } $member = new Member(); $member->setId($response->getId()); $member->setUsername($response->getEmail()); $member->setPassword($response->getPassword()); $member->setCompanyId($response->getCompanyId()); $member->setFirstname($response->getFirstname()); $member->setLastname($response->getLastname()); $member->setIsManager($response->isManager()); $member->setIsEnabled($response->isEnabled()); return $member; } public function refreshUser(UserInterface $user) { if (!$user instanceof Member) { throw new UnsupportedUserException( sprintf('Instances of "%s" are not supported.', get_class($user)) ); } return $this->loadUserByUsername($user->getUsername()); } public function supportsClass($class) { return $class === Member::class; } } 

AppBundle / Безопасность / Пользователь / Member.php

 <?php namespace AppBundle\Security\User; use Symfony\Component\Security\Core\User\UserInterface; class Member implements UserInterface { private $id; private $username; private $password; private $companyId; private $firstname; private $lastname; private $isManager; private $isEnabled; private $roles = ['ROLE_USER']; public function getId() { return $this->id; } public function setId($id) { $this->id = $id; return $this; } public function getUsername() { return $this->username; } public function setUsername($username) { $this->username = $username; return $this; } public function getPassword() { return $this->password; } public function setPassword($password) { $this->password = $password; return $this; } public function getCompanyId() { return $this->companyId; } public function setCompanyId($companyId) { $this->companyId = $companyId; return $this; } public function getFirstname() { return $this->firstname; } public function setFirstname($firstname) { $this->firstname = $firstname; return $this; } public function getLastname() { return $this->lastname; } public function setLastname($lastname) { $this->lastname = $lastname; return $this; } public function isManager() { return $this->isManager; } public function setIsManager($isManager) { $this->isManager = $isManager; return $this; } public function IsEnabled() { return $this->isEnabled; } public function setIsEnabled($isEnabled) { $this->isEnabled = $isEnabled; return $this; } public function eraseCredentials() { $this->password = null; } public function hasRole($role) { return in_array($role, $this->roles); } public function getRoles() { return $this->roles; } public function addRole($role) { if (!$this->hasRole($role)) { $this->roles[] = $role; } return $this; } public function removeRole($role) { $index = array_search($role, $this->roles); if ($index !== false) { unset($this->roles[$index]); $this->roles = array_values($this->roles); } return $this; } public function getSalt() { return null; } } не <?php namespace AppBundle\Security\User; use Symfony\Component\Security\Core\User\UserInterface; class Member implements UserInterface { private $id; private $username; private $password; private $companyId; private $firstname; private $lastname; private $isManager; private $isEnabled; private $roles = ['ROLE_USER']; public function getId() { return $this->id; } public function setId($id) { $this->id = $id; return $this; } public function getUsername() { return $this->username; } public function setUsername($username) { $this->username = $username; return $this; } public function getPassword() { return $this->password; } public function setPassword($password) { $this->password = $password; return $this; } public function getCompanyId() { return $this->companyId; } public function setCompanyId($companyId) { $this->companyId = $companyId; return $this; } public function getFirstname() { return $this->firstname; } public function setFirstname($firstname) { $this->firstname = $firstname; return $this; } public function getLastname() { return $this->lastname; } public function setLastname($lastname) { $this->lastname = $lastname; return $this; } public function isManager() { return $this->isManager; } public function setIsManager($isManager) { $this->isManager = $isManager; return $this; } public function IsEnabled() { return $this->isEnabled; } public function setIsEnabled($isEnabled) { $this->isEnabled = $isEnabled; return $this; } public function eraseCredentials() { $this->password = null; } public function hasRole($role) { return in_array($role, $this->roles); } public function getRoles() { return $this->roles; } public function addRole($role) { if (!$this->hasRole($role)) { $this->roles[] = $role; } return $this; } public function removeRole($role) { $index = array_search($role, $this->roles); if ($index !== false) { unset($this->roles[$index]); $this->roles = array_values($this->roles); } return $this; } public function getSalt() { return null; } } 

SRC / AppBundle / Ресурсы / конфигурации / services.yml

 imports: parameters: app.provider.member.class: AppBundle\Security\Provider\MemberProvider app.authenticator.form_login.class: AppBundle\Security\Authenticator\FormLoginAuthenticator services: app.provider.member: class: %app.provider.member.class% arguments: ['@gateway'] app.authenticator.form_login: class: %app.authenticator.form_login.class% arguments: ["@service_container"] 

Я нашел свою ошибку после 8 часов тяжелой работы. Обещаю, после этого комментария выпью большую часть пива!

Я Symfony\Component\Security\Core\Authentication\Token\AbstractToken::hasUserChanged() свою проблему в методе Symfony\Component\Security\Core\Authentication\Token\AbstractToken::hasUserChanged() , который сравнивает пользователя, хранящегося в сеансе, и тот, который возвращает refreshUser вашего провайдера.

Из-за этого условия мой пользовательский объект считался измененным :

  if ($this->user->getPassword() !== $user->getPassword()) { return true; } 

Фактически, перед сохранением в сеансе метод eraseCredentials() вызывается в вашей пользовательской сущности, чтобы пароль был удален. Но пароль существует у пользователя, которого возвращает поставщик.

Вот почему в документах они показывают свойства plainPassword и password … Они сохраняют password в сеансе, а eraseCredentials просто очищает `plainPassword. Какой-то хитрый.

У нас есть 2 решения:

  • с eraseCredentials не касающимся пароля, может быть полезно, если вы хотите отключить свой член, когда он каким-то образом изменит свой пароль.

  • реализуя EquatableInterface в нашей пользовательской сущности, потому что следующий тест вызывается перед вышеописанным.

     if ($this->user instanceof EquatableInterface) { return !(bool) $this->user->isEqualTo($user); } 

Я решил реализовать EquatableInterface в моей пользовательской сущности, и я никогда не забуду делать это в будущем.

 <?php namespace AppBundle\Security\User; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\EquatableInterface; class Member implements UserInterface, EquatableInterface { // (...) public function isEqualTo(UserInterface $user) { return $user->getId() === $this->getId(); } }