vendor/symfony/security-http/RememberMe/AbstractRememberMeHandler.php line 63

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  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\RememberMe;
  11. use Psr\Log\LoggerInterface;
  12. use Symfony\Component\HttpFoundation\Cookie;
  13. use Symfony\Component\HttpFoundation\RequestStack;
  14. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  15. use Symfony\Component\Security\Core\User\UserInterface;
  16. use Symfony\Component\Security\Core\User\UserProviderInterface;
  17. /**
  18.  * @author Wouter de Jong <wouter@wouterj.nl>
  19.  */
  20. abstract class AbstractRememberMeHandler implements RememberMeHandlerInterface
  21. {
  22.     private $userProvider;
  23.     protected $requestStack;
  24.     protected $options;
  25.     protected $logger;
  26.     public function __construct(UserProviderInterface $userProviderRequestStack $requestStack, array $options = [], LoggerInterface $logger null)
  27.     {
  28.         $this->userProvider $userProvider;
  29.         $this->requestStack $requestStack;
  30.         $this->options $options + [
  31.             'name' => 'REMEMBERME',
  32.             'lifetime' => 31536000,
  33.             'path' => '/',
  34.             'domain' => null,
  35.             'secure' => false,
  36.             'httponly' => true,
  37.             'samesite' => null,
  38.             'always_remember_me' => false,
  39.             'remember_me_parameter' => '_remember_me',
  40.         ];
  41.         $this->logger $logger;
  42.     }
  43.     /**
  44.      * Checks if the RememberMeDetails is a valid cookie to login the given User.
  45.      *
  46.      * This method should also:
  47.      * - Create a new remember-me cookie to be sent with the response (using {@see createCookie()});
  48.      * - If you store the token somewhere else (e.g. in a database), invalidate the stored token.
  49.      *
  50.      * @throws AuthenticationException throw this exception if the remember me details are not accepted
  51.      */
  52.     abstract protected function processRememberMe(RememberMeDetails $rememberMeDetailsUserInterface $user): void;
  53.     /**
  54.      * {@inheritdoc}
  55.      */
  56.     public function consumeRememberMeCookie(RememberMeDetails $rememberMeDetails): UserInterface
  57.     {
  58.         try {
  59.             // @deprecated since Symfony 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
  60.             $method 'loadUserByIdentifier';
  61.             if (!method_exists($this->userProvider'loadUserByIdentifier')) {
  62.                 trigger_deprecation('symfony/security-core''5.3''Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.'get_debug_type($this->userProvider));
  63.                 $method 'loadUserByUsername';
  64.             }
  65.             $user $this->userProvider->$method($rememberMeDetails->getUserIdentifier());
  66.         } catch (AuthenticationException $e) {
  67.             throw $e;
  68.         }
  69.         if (!$user instanceof UserInterface) {
  70.             throw new \LogicException(sprintf('The UserProviderInterface implementation must return an instance of UserInterface, but returned "%s".'get_debug_type($user)));
  71.         }
  72.         $this->processRememberMe($rememberMeDetails$user);
  73.         if (null !== $this->logger) {
  74.             $this->logger->info('Remember-me cookie accepted.');
  75.         }
  76.         return $user;
  77.     }
  78.     /**
  79.      * {@inheritdoc}
  80.      */
  81.     public function clearRememberMeCookie(): void
  82.     {
  83.         if (null !== $this->logger) {
  84.             $this->logger->debug('Clearing remember-me cookie.', ['name' => $this->options['name']]);
  85.         }
  86.         $this->createCookie(null);
  87.     }
  88.     /**
  89.      * Creates the remember-me cookie using the correct configuration.
  90.      *
  91.      * @param RememberMeDetails|null $rememberMeDetails The details for the cookie, or null to clear the remember-me cookie
  92.      */
  93.     protected function createCookie(?RememberMeDetails $rememberMeDetails)
  94.     {
  95.         $request $this->requestStack->getMainRequest();
  96.         if (!$request) {
  97.             throw new \LogicException('Cannot create the remember-me cookie; no master request available.');
  98.         }
  99.         // the ResponseListener configures the cookie saved in this attribute on the final response object
  100.         $request->attributes->set(ResponseListener::COOKIE_ATTR_NAME, new Cookie(
  101.             $this->options['name'],
  102.             $rememberMeDetails $rememberMeDetails->toString() : null,
  103.             $rememberMeDetails $rememberMeDetails->getExpires() : 1,
  104.             $this->options['path'],
  105.             $this->options['domain'],
  106.             $this->options['secure'] ?? $request->isSecure(),
  107.             $this->options['httponly'],
  108.             false,
  109.             $this->options['samesite']
  110.         ));
  111.     }
  112. }