vendor/symfony/security-core/Authentication/Token/AbstractToken.php line 60

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\Core\Authentication\Token;
  11. use Symfony\Component\Security\Core\User\EquatableInterface;
  12. use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
  13. use Symfony\Component\Security\Core\User\UserInterface;
  14. /**
  15.  * Base class for Token instances.
  16.  *
  17.  * @author Fabien Potencier <fabien@symfony.com>
  18.  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  19.  */
  20. abstract class AbstractToken implements TokenInterface
  21. {
  22.     private $user;
  23.     private $roleNames = [];
  24.     private $authenticated false;
  25.     private $attributes = [];
  26.     /**
  27.      * @param string[] $roles An array of roles
  28.      *
  29.      * @throws \InvalidArgumentException
  30.      */
  31.     public function __construct(array $roles = [])
  32.     {
  33.         foreach ($roles as $role) {
  34.             $this->roleNames[] = $role;
  35.         }
  36.     }
  37.     /**
  38.      * {@inheritdoc}
  39.      */
  40.     public function getRoleNames(): array
  41.     {
  42.         return $this->roleNames;
  43.     }
  44.     /**
  45.      * {@inheritdoc}
  46.      */
  47.     public function getUsername(/* $legacy = true */)
  48.     {
  49.         if (=== \func_num_args() && false === func_get_arg(0)) {
  50.             return null;
  51.         }
  52.         trigger_deprecation('symfony/security-core''5.3''Method "%s()" is deprecated, use getUserIdentifier() instead.'__METHOD__);
  53.         if ($this->user instanceof UserInterface) {
  54.             return method_exists($this->user'getUserIdentifier') ? $this->user->getUserIdentifier() : $this->user->getUsername();
  55.         }
  56.         return (string) $this->user;
  57.     }
  58.     /**
  59.      * {@inheritdoc}
  60.      */
  61.     public function getUserIdentifier(): string
  62.     {
  63.         // method returns "null" in non-legacy mode if not overridden
  64.         $username $this->getUsername(false);
  65.         if (null !== $username) {
  66.             trigger_deprecation('symfony/security-core''5.3''Method "%s::getUsername()" is deprecated, override "getUserIdentifier()" instead.'get_debug_type($this));
  67.         }
  68.         if ($this->user instanceof UserInterface) {
  69.             // @deprecated since Symfony 5.3, change to $user->getUserIdentifier() in 6.0
  70.             return method_exists($this->user'getUserIdentifier') ? $this->user->getUserIdentifier() : $this->user->getUsername();
  71.         }
  72.         return (string) $this->user;
  73.     }
  74.     /**
  75.      * {@inheritdoc}
  76.      */
  77.     public function getUser()
  78.     {
  79.         return $this->user;
  80.     }
  81.     /**
  82.      * {@inheritdoc}
  83.      */
  84.     public function setUser($user)
  85.     {
  86.         if (!($user instanceof UserInterface || (\is_object($user) && method_exists($user'__toString')) || \is_string($user))) {
  87.             throw new \InvalidArgumentException('$user must be an instanceof UserInterface, an object implementing a __toString method, or a primitive string.');
  88.         }
  89.         if (!$user instanceof UserInterface) {
  90.             trigger_deprecation('symfony/security-core''5.4''Using an object that is not an instance of "%s" as $user in "%s" is deprecated.'UserInterface::class, static::class);
  91.         }
  92.         // @deprecated since Symfony 5.4, remove the whole block if/elseif/else block in 6.0
  93.         if (\func_num_args() && !func_get_arg(1)) {
  94.             // ContextListener checks if the user has changed on its own and calls `setAuthenticated()` subsequently,
  95.             // avoid doing the same checks twice
  96.             $changed false;
  97.         } elseif (null === $this->user) {
  98.             $changed false;
  99.         } elseif ($this->user instanceof UserInterface) {
  100.             if (!$user instanceof UserInterface) {
  101.                 $changed true;
  102.             } else {
  103.                 $changed $this->hasUserChanged($user);
  104.             }
  105.         } elseif ($user instanceof UserInterface) {
  106.             $changed true;
  107.         } else {
  108.             $changed = (string) $this->user !== (string) $user;
  109.         }
  110.         // @deprecated since Symfony 5.4
  111.         if ($changed) {
  112.             $this->setAuthenticated(falsefalse);
  113.         }
  114.         $this->user $user;
  115.     }
  116.     /**
  117.      * {@inheritdoc}
  118.      *
  119.      * @deprecated since Symfony 5.4
  120.      */
  121.     public function isAuthenticated()
  122.     {
  123.         if (\func_num_args() || func_get_arg(0)) {
  124.             trigger_deprecation('symfony/security-core''5.4''Method "%s()" is deprecated, return null from "getUser()" instead when a token is not authenticated.'__METHOD__);
  125.         }
  126.         return $this->authenticated;
  127.     }
  128.     /**
  129.      * {@inheritdoc}
  130.      */
  131.     public function setAuthenticated(bool $authenticated)
  132.     {
  133.         if (\func_num_args() || func_get_arg(1)) {
  134.             trigger_deprecation('symfony/security-core''5.4''Method "%s()" is deprecated'__METHOD__);
  135.         }
  136.         $this->authenticated $authenticated;
  137.     }
  138.     /**
  139.      * {@inheritdoc}
  140.      */
  141.     public function eraseCredentials()
  142.     {
  143.         if ($this->getUser() instanceof UserInterface) {
  144.             $this->getUser()->eraseCredentials();
  145.         }
  146.     }
  147.     /**
  148.      * Returns all the necessary state of the object for serialization purposes.
  149.      *
  150.      * There is no need to serialize any entry, they should be returned as-is.
  151.      * If you extend this method, keep in mind you MUST guarantee parent data is present in the state.
  152.      * Here is an example of how to extend this method:
  153.      * <code>
  154.      *     public function __serialize(): array
  155.      *     {
  156.      *         return [$this->childAttribute, parent::__serialize()];
  157.      *     }
  158.      * </code>
  159.      *
  160.      * @see __unserialize()
  161.      */
  162.     public function __serialize(): array
  163.     {
  164.         return [$this->user$this->authenticatednull$this->attributes$this->roleNames];
  165.     }
  166.     /**
  167.      * Restores the object state from an array given by __serialize().
  168.      *
  169.      * There is no need to unserialize any entry in $data, they are already ready-to-use.
  170.      * If you extend this method, keep in mind you MUST pass the parent data to its respective class.
  171.      * Here is an example of how to extend this method:
  172.      * <code>
  173.      *     public function __unserialize(array $data): void
  174.      *     {
  175.      *         [$this->childAttribute, $parentData] = $data;
  176.      *         parent::__unserialize($parentData);
  177.      *     }
  178.      * </code>
  179.      *
  180.      * @see __serialize()
  181.      */
  182.     public function __unserialize(array $data): void
  183.     {
  184.         [$this->user$this->authenticated, , $this->attributes$this->roleNames] = $data;
  185.     }
  186.     /**
  187.      * {@inheritdoc}
  188.      */
  189.     public function getAttributes()
  190.     {
  191.         return $this->attributes;
  192.     }
  193.     /**
  194.      * {@inheritdoc}
  195.      */
  196.     public function setAttributes(array $attributes)
  197.     {
  198.         $this->attributes $attributes;
  199.     }
  200.     /**
  201.      * {@inheritdoc}
  202.      */
  203.     public function hasAttribute(string $name)
  204.     {
  205.         return \array_key_exists($name$this->attributes);
  206.     }
  207.     /**
  208.      * {@inheritdoc}
  209.      */
  210.     public function getAttribute(string $name)
  211.     {
  212.         if (!\array_key_exists($name$this->attributes)) {
  213.             throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.'$name));
  214.         }
  215.         return $this->attributes[$name];
  216.     }
  217.     /**
  218.      * {@inheritdoc}
  219.      */
  220.     public function setAttribute(string $name$value)
  221.     {
  222.         $this->attributes[$name] = $value;
  223.     }
  224.     /**
  225.      * {@inheritdoc}
  226.      */
  227.     public function __toString()
  228.     {
  229.         $class = static::class;
  230.         $class substr($classstrrpos($class'\\') + 1);
  231.         $roles = [];
  232.         foreach ($this->roleNames as $role) {
  233.             $roles[] = $role;
  234.         }
  235.         return sprintf('%s(user="%s", authenticated=%s, roles="%s")'$class$this->getUserIdentifier(), json_encode($this->authenticated), implode(', '$roles));
  236.     }
  237.     /**
  238.      * @internal
  239.      */
  240.     final public function serialize(): string
  241.     {
  242.         return serialize($this->__serialize());
  243.     }
  244.     /**
  245.      * @internal
  246.      */
  247.     final public function unserialize($serialized)
  248.     {
  249.         $this->__unserialize(\is_array($serialized) ? $serialized unserialize($serialized));
  250.     }
  251.     /**
  252.      * @deprecated since Symfony 5.4
  253.      */
  254.     private function hasUserChanged(UserInterface $user): bool
  255.     {
  256.         if (!($this->user instanceof UserInterface)) {
  257.             throw new \BadMethodCallException('Method "hasUserChanged" should be called when current user class is instance of "UserInterface".');
  258.         }
  259.         if ($this->user instanceof EquatableInterface) {
  260.             return !(bool) $this->user->isEqualTo($user);
  261.         }
  262.         // @deprecated since Symfony 5.3, check for PasswordAuthenticatedUserInterface on both user objects before comparing passwords
  263.         if ($this->user->getPassword() !== $user->getPassword()) {
  264.             return true;
  265.         }
  266.         // @deprecated since Symfony 5.3, check for LegacyPasswordAuthenticatedUserInterface on both user objects before comparing salts
  267.         if ($this->user->getSalt() !== $user->getSalt()) {
  268.             return true;
  269.         }
  270.         $userRoles array_map('strval', (array) $user->getRoles());
  271.         if ($this instanceof SwitchUserToken) {
  272.             $userRoles[] = 'ROLE_PREVIOUS_ADMIN';
  273.         }
  274.         if (\count($userRoles) !== \count($this->getRoleNames()) || \count($userRoles) !== \count(array_intersect($userRoles$this->getRoleNames()))) {
  275.             return true;
  276.         }
  277.         // @deprecated since Symfony 5.3, drop getUsername() in 6.0
  278.         $userIdentifier = function ($user) {
  279.             return method_exists($user'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername();
  280.         };
  281.         if ($userIdentifier($this->user) !== $userIdentifier($user)) {
  282.             return true;
  283.         }
  284.         return false;
  285.     }
  286. }