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.     public function getUserIdentifier(): string
  59.     {
  60.         // method returns "null" in non-legacy mode if not overridden
  61.         $username $this->getUsername(false);
  62.         if (null !== $username) {
  63.             trigger_deprecation('symfony/security-core''5.3''Method "%s::getUsername()" is deprecated, override "getUserIdentifier()" instead.'get_debug_type($this));
  64.         }
  65.         if ($this->user instanceof UserInterface) {
  66.             // @deprecated since 5.3, change to $user->getUserIdentifier() in 6.0
  67.             return method_exists($this->user'getUserIdentifier') ? $this->user->getUserIdentifier() : $this->user->getUsername();
  68.         }
  69.         return (string) $this->user;
  70.     }
  71.     /**
  72.      * {@inheritdoc}
  73.      */
  74.     public function getUser()
  75.     {
  76.         return $this->user;
  77.     }
  78.     /**
  79.      * {@inheritdoc}
  80.      */
  81.     public function setUser($user)
  82.     {
  83.         if (!($user instanceof UserInterface || (\is_object($user) && method_exists($user'__toString')) || \is_string($user))) {
  84.             throw new \InvalidArgumentException('$user must be an instanceof UserInterface, an object implementing a __toString method, or a primitive string.');
  85.         }
  86.         if (null === $this->user) {
  87.             $changed false;
  88.         } elseif ($this->user instanceof UserInterface) {
  89.             if (!$user instanceof UserInterface) {
  90.                 $changed true;
  91.             } else {
  92.                 $changed $this->hasUserChanged($user);
  93.             }
  94.         } elseif ($user instanceof UserInterface) {
  95.             $changed true;
  96.         } else {
  97.             $changed = (string) $this->user !== (string) $user;
  98.         }
  99.         if ($changed) {
  100.             $this->setAuthenticated(false);
  101.         }
  102.         $this->user $user;
  103.     }
  104.     /**
  105.      * {@inheritdoc}
  106.      */
  107.     public function isAuthenticated()
  108.     {
  109.         return $this->authenticated;
  110.     }
  111.     /**
  112.      * {@inheritdoc}
  113.      */
  114.     public function setAuthenticated(bool $authenticated)
  115.     {
  116.         $this->authenticated $authenticated;
  117.     }
  118.     /**
  119.      * {@inheritdoc}
  120.      */
  121.     public function eraseCredentials()
  122.     {
  123.         if ($this->getUser() instanceof UserInterface) {
  124.             $this->getUser()->eraseCredentials();
  125.         }
  126.     }
  127.     /**
  128.      * Returns all the necessary state of the object for serialization purposes.
  129.      *
  130.      * There is no need to serialize any entry, they should be returned as-is.
  131.      * If you extend this method, keep in mind you MUST guarantee parent data is present in the state.
  132.      * Here is an example of how to extend this method:
  133.      * <code>
  134.      *     public function __serialize(): array
  135.      *     {
  136.      *         return [$this->childAttribute, parent::__serialize()];
  137.      *     }
  138.      * </code>
  139.      *
  140.      * @see __unserialize()
  141.      */
  142.     public function __serialize(): array
  143.     {
  144.         return [$this->user$this->authenticatednull$this->attributes$this->roleNames];
  145.     }
  146.     /**
  147.      * Restores the object state from an array given by __serialize().
  148.      *
  149.      * There is no need to unserialize any entry in $data, they are already ready-to-use.
  150.      * If you extend this method, keep in mind you MUST pass the parent data to its respective class.
  151.      * Here is an example of how to extend this method:
  152.      * <code>
  153.      *     public function __unserialize(array $data): void
  154.      *     {
  155.      *         [$this->childAttribute, $parentData] = $data;
  156.      *         parent::__unserialize($parentData);
  157.      *     }
  158.      * </code>
  159.      *
  160.      * @see __serialize()
  161.      */
  162.     public function __unserialize(array $data): void
  163.     {
  164.         [$this->user$this->authenticated, , $this->attributes$this->roleNames] = $data;
  165.     }
  166.     /**
  167.      * Returns the token attributes.
  168.      *
  169.      * @return array The token attributes
  170.      */
  171.     public function getAttributes()
  172.     {
  173.         return $this->attributes;
  174.     }
  175.     /**
  176.      * Sets the token attributes.
  177.      *
  178.      * @param array $attributes The token attributes
  179.      */
  180.     public function setAttributes(array $attributes)
  181.     {
  182.         $this->attributes $attributes;
  183.     }
  184.     /**
  185.      * Returns true if the attribute exists.
  186.      *
  187.      * @return bool true if the attribute exists, false otherwise
  188.      */
  189.     public function hasAttribute(string $name)
  190.     {
  191.         return \array_key_exists($name$this->attributes);
  192.     }
  193.     /**
  194.      * Returns an attribute value.
  195.      *
  196.      * @return mixed The attribute value
  197.      *
  198.      * @throws \InvalidArgumentException When attribute doesn't exist for this token
  199.      */
  200.     public function getAttribute(string $name)
  201.     {
  202.         if (!\array_key_exists($name$this->attributes)) {
  203.             throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.'$name));
  204.         }
  205.         return $this->attributes[$name];
  206.     }
  207.     /**
  208.      * Sets an attribute.
  209.      *
  210.      * @param mixed $value The attribute value
  211.      */
  212.     public function setAttribute(string $name$value)
  213.     {
  214.         $this->attributes[$name] = $value;
  215.     }
  216.     /**
  217.      * {@inheritdoc}
  218.      */
  219.     public function __toString()
  220.     {
  221.         $class = static::class;
  222.         $class substr($classstrrpos($class'\\') + 1);
  223.         $roles = [];
  224.         foreach ($this->roleNames as $role) {
  225.             $roles[] = $role;
  226.         }
  227.         return sprintf('%s(user="%s", authenticated=%s, roles="%s")'$class$this->getUserIdentifier(), json_encode($this->authenticated), implode(', '$roles));
  228.     }
  229.     /**
  230.      * @internal
  231.      */
  232.     final public function serialize(): string
  233.     {
  234.         return serialize($this->__serialize());
  235.     }
  236.     /**
  237.      * @internal
  238.      */
  239.     final public function unserialize($serialized)
  240.     {
  241.         $this->__unserialize(\is_array($serialized) ? $serialized unserialize($serialized));
  242.     }
  243.     private function hasUserChanged(UserInterface $user): bool
  244.     {
  245.         if (!($this->user instanceof UserInterface)) {
  246.             throw new \BadMethodCallException('Method "hasUserChanged" should be called when current user class is instance of "UserInterface".');
  247.         }
  248.         if ($this->user instanceof EquatableInterface) {
  249.             return !(bool) $this->user->isEqualTo($user);
  250.         }
  251.         // @deprecated since Symfony 5.3, check for PasswordAuthenticatedUserInterface on both user objects before comparing passwords
  252.         if ($this->user->getPassword() !== $user->getPassword()) {
  253.             return true;
  254.         }
  255.         // @deprecated since Symfony 5.3, check for LegacyPasswordAuthenticatedUserInterface on both user objects before comparing salts
  256.         if ($this->user->getSalt() !== $user->getSalt()) {
  257.             return true;
  258.         }
  259.         $userRoles array_map('strval', (array) $user->getRoles());
  260.         if ($this instanceof SwitchUserToken) {
  261.             $userRoles[] = 'ROLE_PREVIOUS_ADMIN';
  262.         }
  263.         if (\count($userRoles) !== \count($this->getRoleNames()) || \count($userRoles) !== \count(array_intersect($userRoles$this->getRoleNames()))) {
  264.             return true;
  265.         }
  266.         // @deprecated since Symfony 5.3, drop getUsername() in 6.0
  267.         $userIdentifier = function ($user) {
  268.             return method_exists($user'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername();
  269.         };
  270.         if ($userIdentifier($this->user) !== $userIdentifier($user)) {
  271.             return true;
  272.         }
  273.         return false;
  274.     }
  275. }