vendor/symfony/security-http/EventListener/PasswordMigratingListener.php line 45

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <[email protected]>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Security\Http\EventListener;
  11. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  12. use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
  13. use Symfony\Component\PasswordHasher\PasswordHasherInterface;
  14. use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
  15. use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
  16. use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
  17. use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
  18. use Symfony\Component\Security\Http\Authenticator\Passport\UserPassportInterface;
  19. use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
  20. /**
  21.  * @author Wouter de Jong <[email protected]>
  22.  *
  23.  * @final
  24.  */
  25. class PasswordMigratingListener implements EventSubscriberInterface
  26. {
  27.     private $hasherFactory;
  28.     /**
  29.      * @param PasswordHasherFactoryInterface $hasherFactory
  30.      */
  31.     public function __construct($hasherFactory)
  32.     {
  33.         if ($hasherFactory instanceof EncoderFactoryInterface) {
  34.             trigger_deprecation('symfony/security-core''5.3''Passing a "%s" instance to the "%s" constructor is deprecated, use "%s" instead.'EncoderFactoryInterface::class, __CLASS__PasswordHasherFactoryInterface::class);
  35.         }
  36.         $this->hasherFactory $hasherFactory;
  37.     }
  38.     public function onLoginSuccess(LoginSuccessEvent $event): void
  39.     {
  40.         $passport $event->getPassport();
  41.         if (!$passport instanceof UserPassportInterface || !$passport->hasBadge(PasswordUpgradeBadge::class)) {
  42.             return;
  43.         }
  44.         /** @var PasswordUpgradeBadge $badge */
  45.         $badge $passport->getBadge(PasswordUpgradeBadge::class);
  46.         $plaintextPassword $badge->getAndErasePlaintextPassword();
  47.         if ('' === $plaintextPassword) {
  48.             return;
  49.         }
  50.         $user $passport->getUser();
  51.         if (null === $user->getPassword()) {
  52.             return;
  53.         }
  54.         $passwordHasher $this->hasherFactory instanceof EncoderFactoryInterface $this->hasherFactory->getEncoder($user) : $this->hasherFactory->getPasswordHasher($user);
  55.         if (!$passwordHasher->needsRehash($user->getPassword())) {
  56.             return;
  57.         }
  58.         $passwordUpgrader $badge->getPasswordUpgrader();
  59.         if (null === $passwordUpgrader) {
  60.             if (!$passport->hasBadge(UserBadge::class)) {
  61.                 return;
  62.             }
  63.             /** @var UserBadge $userBadge */
  64.             $userBadge $passport->getBadge(UserBadge::class);
  65.             $userLoader $userBadge->getUserLoader();
  66.             if (\is_array($userLoader) && $userLoader[0] instanceof PasswordUpgraderInterface) {
  67.                 $passwordUpgrader $userLoader[0];
  68.             } elseif (!$userLoader instanceof \Closure
  69.                 || !($passwordUpgrader = (new \ReflectionFunction($userLoader))->getClosureThis()) instanceof PasswordUpgraderInterface
  70.             ) {
  71.                 return;
  72.             }
  73.         }
  74.         $passwordUpgrader->upgradePassword($user$passwordHasher instanceof PasswordHasherInterface $passwordHasher->hash($plaintextPassword$user->getSalt()) : $passwordHasher->encodePassword($plaintextPassword$user->getSalt()));
  75.     }
  76.     public static function getSubscribedEvents(): array
  77.     {
  78.         return [LoginSuccessEvent::class => 'onLoginSuccess'];
  79.     }
  80. }