123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- <?php
- /*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace Symfony\Component\Security\Core\Authentication\Token;
- use Symfony\Component\Security\Core\User\EquatableInterface;
- use Symfony\Component\Security\Core\User\UserInterface;
- /**
- * Base class for Token instances.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- * @author Johannes M. Schmitt <schmittjoh@gmail.com>
- */
- abstract class AbstractToken implements TokenInterface
- {
- private $user;
- private $roleNames = [];
- private $authenticated = false;
- private $attributes = [];
- /**
- * @param string[] $roles An array of roles
- *
- * @throws \InvalidArgumentException
- */
- public function __construct(array $roles = [])
- {
- foreach ($roles as $role) {
- $this->roleNames[] = $role;
- }
- }
- /**
- * {@inheritdoc}
- */
- public function getRoleNames(): array
- {
- return $this->roleNames;
- }
- /**
- * {@inheritdoc}
- */
- public function getUsername()
- {
- if ($this->user instanceof UserInterface) {
- return $this->user->getUsername();
- }
- return (string) $this->user;
- }
- /**
- * {@inheritdoc}
- */
- public function getUser()
- {
- return $this->user;
- }
- /**
- * {@inheritdoc}
- */
- public function setUser($user)
- {
- if (!($user instanceof UserInterface || (\is_object($user) && method_exists($user, '__toString')) || \is_string($user))) {
- throw new \InvalidArgumentException('$user must be an instanceof UserInterface, an object implementing a __toString method, or a primitive string.');
- }
- if (null === $this->user) {
- $changed = false;
- } elseif ($this->user instanceof UserInterface) {
- if (!$user instanceof UserInterface) {
- $changed = true;
- } else {
- $changed = $this->hasUserChanged($user);
- }
- } elseif ($user instanceof UserInterface) {
- $changed = true;
- } else {
- $changed = (string) $this->user !== (string) $user;
- }
- if ($changed) {
- $this->setAuthenticated(false);
- }
- $this->user = $user;
- }
- /**
- * {@inheritdoc}
- */
- public function isAuthenticated()
- {
- return $this->authenticated;
- }
- /**
- * {@inheritdoc}
- */
- public function setAuthenticated(bool $authenticated)
- {
- $this->authenticated = $authenticated;
- }
- /**
- * {@inheritdoc}
- */
- public function eraseCredentials()
- {
- if ($this->getUser() instanceof UserInterface) {
- $this->getUser()->eraseCredentials();
- }
- }
- /**
- * Returns all the necessary state of the object for serialization purposes.
- *
- * There is no need to serialize any entry, they should be returned as-is.
- * If you extend this method, keep in mind you MUST guarantee parent data is present in the state.
- * Here is an example of how to extend this method:
- * <code>
- * public function __serialize(): array
- * {
- * return [$this->childAttribute, parent::__serialize()];
- * }
- * </code>
- *
- * @see __unserialize()
- */
- public function __serialize(): array
- {
- return [$this->user, $this->authenticated, null, $this->attributes, $this->roleNames];
- }
- /**
- * Restores the object state from an array given by __serialize().
- *
- * There is no need to unserialize any entry in $data, they are already ready-to-use.
- * If you extend this method, keep in mind you MUST pass the parent data to its respective class.
- * Here is an example of how to extend this method:
- * <code>
- * public function __unserialize(array $data): void
- * {
- * [$this->childAttribute, $parentData] = $data;
- * parent::__unserialize($parentData);
- * }
- * </code>
- *
- * @see __serialize()
- */
- public function __unserialize(array $data): void
- {
- [$this->user, $this->authenticated, , $this->attributes, $this->roleNames] = $data;
- }
- /**
- * Returns the token attributes.
- *
- * @return array The token attributes
- */
- public function getAttributes()
- {
- return $this->attributes;
- }
- /**
- * Sets the token attributes.
- *
- * @param array $attributes The token attributes
- */
- public function setAttributes(array $attributes)
- {
- $this->attributes = $attributes;
- }
- /**
- * Returns true if the attribute exists.
- *
- * @return bool true if the attribute exists, false otherwise
- */
- public function hasAttribute(string $name)
- {
- return \array_key_exists($name, $this->attributes);
- }
- /**
- * Returns an attribute value.
- *
- * @return mixed The attribute value
- *
- * @throws \InvalidArgumentException When attribute doesn't exist for this token
- */
- public function getAttribute(string $name)
- {
- if (!\array_key_exists($name, $this->attributes)) {
- throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.', $name));
- }
- return $this->attributes[$name];
- }
- /**
- * Sets an attribute.
- *
- * @param mixed $value The attribute value
- */
- public function setAttribute(string $name, $value)
- {
- $this->attributes[$name] = $value;
- }
- /**
- * {@inheritdoc}
- */
- public function __toString()
- {
- $class = static::class;
- $class = substr($class, strrpos($class, '\\') + 1);
- $roles = [];
- foreach ($this->roleNames as $role) {
- $roles[] = $role;
- }
- return sprintf('%s(user="%s", authenticated=%s, roles="%s")', $class, $this->getUsername(), json_encode($this->authenticated), implode(', ', $roles));
- }
- /**
- * @internal
- */
- final public function serialize(): string
- {
- return serialize($this->__serialize());
- }
- /**
- * @internal
- */
- final public function unserialize($serialized)
- {
- $this->__unserialize(\is_array($serialized) ? $serialized : unserialize($serialized));
- }
- private function hasUserChanged(UserInterface $user): bool
- {
- if (!($this->user instanceof UserInterface)) {
- throw new \BadMethodCallException('Method "hasUserChanged" should be called when current user class is instance of "UserInterface".');
- }
- if ($this->user instanceof EquatableInterface) {
- return !(bool) $this->user->isEqualTo($user);
- }
- if ($this->user->getPassword() !== $user->getPassword()) {
- return true;
- }
- if ($this->user->getSalt() !== $user->getSalt()) {
- return true;
- }
- $userRoles = array_map('strval', (array) $user->getRoles());
- if ($this instanceof SwitchUserToken) {
- $userRoles[] = 'ROLE_PREVIOUS_ADMIN';
- }
- if (\count($userRoles) !== \count($this->getRoleNames()) || \count($userRoles) !== \count(array_intersect($userRoles, $this->getRoleNames()))) {
- return true;
- }
- if ($this->user->getUsername() !== $user->getUsername()) {
- return true;
- }
- return false;
- }
- }
|