vendor/symfony/security-csrf/TokenStorage/SessionTokenStorage.php line 98

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\Csrf\TokenStorage;
  11. use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpFoundation\RequestStack;
  14. use Symfony\Component\HttpFoundation\Session\Session;
  15. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  16. use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
  17. use Symfony\Component\Security\Csrf\Exception\TokenNotFoundException;
  18. /**
  19. * Token storage that uses a Symfony Session object.
  20. *
  21. * @author Bernhard Schussek <bschussek@gmail.com>
  22. */
  23. class SessionTokenStorage implements ClearableTokenStorageInterface
  24. {
  25. /**
  26. * The namespace used to store values in the session.
  27. */
  28. public const SESSION_NAMESPACE = '_csrf';
  29. private $requestStack;
  30. private $namespace;
  31. /**
  32. * To be removed in Symfony 6.0.
  33. */
  34. private $session;
  35. /**
  36. * Initializes the storage with a RequestStack object and a session namespace.
  37. *
  38. * @param RequestStack $requestStack
  39. * @param string $namespace The namespace under which the token is stored in the requestStack
  40. */
  41. public function __construct(/* RequestStack */ $requestStack, string $namespace = self::SESSION_NAMESPACE)
  42. {
  43. if ($requestStack instanceof SessionInterface) {
  44. trigger_deprecation('symfony/security-csrf', '5.3', 'Passing a "%s" to "%s" is deprecated, use a "%s" instead.', SessionInterface::class, __CLASS__, RequestStack::class);
  45. $request = new Request();
  46. $request->setSession($requestStack);
  47. $requestStack = new RequestStack();
  48. $requestStack->push($request);
  49. }
  50. $this->requestStack = $requestStack;
  51. $this->namespace = $namespace;
  52. }
  53. /**
  54. * {@inheritdoc}
  55. */
  56. public function getToken(string $tokenId)
  57. {
  58. $session = $this->getSession();
  59. if (!$session->isStarted()) {
  60. $session->start();
  61. }
  62. if (!$session->has($this->namespace.'/'.$tokenId)) {
  63. throw new TokenNotFoundException('The CSRF token with ID '.$tokenId.' does not exist.');
  64. }
  65. return (string) $session->get($this->namespace.'/'.$tokenId);
  66. }
  67. /**
  68. * {@inheritdoc}
  69. */
  70. public function setToken(string $tokenId, string $token)
  71. {
  72. $session = $this->getSession();
  73. if (!$session->isStarted()) {
  74. $session->start();
  75. }
  76. $session->set($this->namespace.'/'.$tokenId, $token);
  77. }
  78. /**
  79. * {@inheritdoc}
  80. */
  81. public function hasToken(string $tokenId)
  82. {
  83. $session = $this->getSession();
  84. if (!$session->isStarted()) {
  85. $session->start();
  86. }
  87. return $session->has($this->namespace.'/'.$tokenId);
  88. }
  89. /**
  90. * {@inheritdoc}
  91. */
  92. public function removeToken(string $tokenId)
  93. {
  94. $session = $this->getSession();
  95. if (!$session->isStarted()) {
  96. $session->start();
  97. }
  98. return $session->remove($this->namespace.'/'.$tokenId);
  99. }
  100. /**
  101. * {@inheritdoc}
  102. */
  103. public function clear()
  104. {
  105. $session = $this->getSession();
  106. foreach (array_keys($session->all()) as $key) {
  107. if (str_starts_with($key, $this->namespace.'/')) {
  108. $session->remove($key);
  109. }
  110. }
  111. }
  112. private function getSession(): SessionInterface
  113. {
  114. try {
  115. return $this->session ?? $this->requestStack->getSession();
  116. } catch (SessionNotFoundException $e) {
  117. trigger_deprecation('symfony/security-csrf', '5.3', 'Using the "%s" without a session has no effect and is deprecated. It will throw a "%s" in Symfony 6.0', __CLASS__, SessionNotFoundException::class);
  118. return $this->session ?? $this->session = new Session(new MockArraySessionStorage());
  119. }
  120. }
  121. }