mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-24 02:58:43 +02:00
N°8771 - Add Symfony form component to iTop core (#760)
- Add Symfony Form Component - Add Symfony CSRF security component - Add iTop default form template - Add Twig debug extension to Twig Environment - Add iTop abstract controller facility to get form builder - Add Twig filter to make trans an alias of dict_s filter
This commit is contained in:
13
lib/symfony/security-csrf/CHANGELOG.md
Normal file
13
lib/symfony/security-csrf/CHANGELOG.md
Normal file
@@ -0,0 +1,13 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
6.0
|
||||
---
|
||||
|
||||
* Remove the `SessionInterface $session` constructor argument of `SessionTokenStorage`, inject a `\Symfony\Component\HttpFoundation\RequestStack $requestStack` instead
|
||||
* Using `SessionTokenStorage` outside a request context throws a `SessionNotFoundException`
|
||||
|
||||
5.3
|
||||
---
|
||||
|
||||
The CHANGELOG for version 5.3 and earlier can be found at https://github.com/symfony/symfony/blob/5.3/src/Symfony/Component/Security/CHANGELOG.md
|
||||
53
lib/symfony/security-csrf/CsrfToken.php
Normal file
53
lib/symfony/security-csrf/CsrfToken.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?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\Csrf;
|
||||
|
||||
/**
|
||||
* A CSRF token.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class CsrfToken
|
||||
{
|
||||
private string $id;
|
||||
private string $value;
|
||||
|
||||
public function __construct(string $id, #[\SensitiveParameter] ?string $value)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->value = $value ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the CSRF token.
|
||||
*/
|
||||
public function getId(): string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the CSRF token.
|
||||
*/
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the CSRF token.
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
141
lib/symfony/security-csrf/CsrfTokenManager.php
Normal file
141
lib/symfony/security-csrf/CsrfTokenManager.php
Normal file
@@ -0,0 +1,141 @@
|
||||
<?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\Csrf;
|
||||
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface;
|
||||
use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator;
|
||||
use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage;
|
||||
use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link CsrfTokenManagerInterface}.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class CsrfTokenManager implements CsrfTokenManagerInterface
|
||||
{
|
||||
private TokenGeneratorInterface $generator;
|
||||
private TokenStorageInterface $storage;
|
||||
private \Closure|string $namespace;
|
||||
|
||||
/**
|
||||
* @param $namespace
|
||||
* * null: generates a namespace using $_SERVER['HTTPS']
|
||||
* * string: uses the given string
|
||||
* * RequestStack: generates a namespace using the current main request
|
||||
* * callable: uses the result of this callable (must return a string)
|
||||
*/
|
||||
public function __construct(?TokenGeneratorInterface $generator = null, ?TokenStorageInterface $storage = null, string|RequestStack|callable|null $namespace = null)
|
||||
{
|
||||
$this->generator = $generator ?? new UriSafeTokenGenerator();
|
||||
$this->storage = $storage ?? new NativeSessionTokenStorage();
|
||||
|
||||
$superGlobalNamespaceGenerator = fn () => !empty($_SERVER['HTTPS']) && 'off' !== strtolower($_SERVER['HTTPS']) ? 'https-' : '';
|
||||
|
||||
if (null === $namespace) {
|
||||
$this->namespace = $superGlobalNamespaceGenerator;
|
||||
} elseif ($namespace instanceof RequestStack) {
|
||||
$this->namespace = function () use ($namespace, $superGlobalNamespaceGenerator) {
|
||||
if ($request = $namespace->getMainRequest()) {
|
||||
return $request->isSecure() ? 'https-' : '';
|
||||
}
|
||||
|
||||
return $superGlobalNamespaceGenerator();
|
||||
};
|
||||
} elseif ($namespace instanceof \Closure || \is_string($namespace)) {
|
||||
$this->namespace = $namespace;
|
||||
} elseif (\is_callable($namespace)) {
|
||||
$this->namespace = $namespace(...);
|
||||
} else {
|
||||
throw new InvalidArgumentException(\sprintf('$namespace must be a string, a callable returning a string, null or an instance of "RequestStack". "%s" given.', get_debug_type($namespace)));
|
||||
}
|
||||
}
|
||||
|
||||
public function getToken(string $tokenId): CsrfToken
|
||||
{
|
||||
$namespacedId = $this->getNamespace().$tokenId;
|
||||
if ($this->storage->hasToken($namespacedId)) {
|
||||
$value = $this->storage->getToken($namespacedId);
|
||||
} else {
|
||||
$value = $this->generator->generateToken();
|
||||
|
||||
$this->storage->setToken($namespacedId, $value);
|
||||
}
|
||||
|
||||
return new CsrfToken($tokenId, $this->randomize($value));
|
||||
}
|
||||
|
||||
public function refreshToken(string $tokenId): CsrfToken
|
||||
{
|
||||
$namespacedId = $this->getNamespace().$tokenId;
|
||||
$value = $this->generator->generateToken();
|
||||
|
||||
$this->storage->setToken($namespacedId, $value);
|
||||
|
||||
return new CsrfToken($tokenId, $this->randomize($value));
|
||||
}
|
||||
|
||||
public function removeToken(string $tokenId): ?string
|
||||
{
|
||||
return $this->storage->removeToken($this->getNamespace().$tokenId);
|
||||
}
|
||||
|
||||
public function isTokenValid(CsrfToken $token): bool
|
||||
{
|
||||
$namespacedId = $this->getNamespace().$token->getId();
|
||||
if (!$this->storage->hasToken($namespacedId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return hash_equals($this->storage->getToken($namespacedId), $this->derandomize($token->getValue()));
|
||||
}
|
||||
|
||||
private function getNamespace(): string
|
||||
{
|
||||
return \is_callable($ns = $this->namespace) ? $ns() : $ns;
|
||||
}
|
||||
|
||||
private function randomize(string $value): string
|
||||
{
|
||||
$key = random_bytes(32);
|
||||
$value = $this->xor($value, $key);
|
||||
|
||||
return \sprintf('%s.%s.%s', substr(hash('xxh128', $key), 0, 1 + (\ord($key[0]) % 32)), rtrim(strtr(base64_encode($key), '+/', '-_'), '='), rtrim(strtr(base64_encode($value), '+/', '-_'), '='));
|
||||
}
|
||||
|
||||
private function derandomize(string $value): string
|
||||
{
|
||||
$parts = explode('.', $value);
|
||||
if (3 !== \count($parts)) {
|
||||
return $value;
|
||||
}
|
||||
$key = base64_decode(strtr($parts[1], '-_', '+/'));
|
||||
if ('' === $key || false === $key) {
|
||||
return $value;
|
||||
}
|
||||
$value = base64_decode(strtr($parts[2], '-_', '+/'));
|
||||
|
||||
return $this->xor($value, $key);
|
||||
}
|
||||
|
||||
private function xor(string $value, string $key): string
|
||||
{
|
||||
if (\strlen($value) > \strlen($key)) {
|
||||
$key = str_repeat($key, ceil(\strlen($value) / \strlen($key)));
|
||||
}
|
||||
|
||||
return $value ^ $key;
|
||||
}
|
||||
}
|
||||
57
lib/symfony/security-csrf/CsrfTokenManagerInterface.php
Normal file
57
lib/symfony/security-csrf/CsrfTokenManagerInterface.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?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\Csrf;
|
||||
|
||||
/**
|
||||
* Manages CSRF tokens.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
interface CsrfTokenManagerInterface
|
||||
{
|
||||
/**
|
||||
* Returns a CSRF token for the given ID.
|
||||
*
|
||||
* If previously no token existed for the given ID, a new token is
|
||||
* generated. Otherwise the existing token is returned (with the same value,
|
||||
* not the same instance).
|
||||
*
|
||||
* @param string $tokenId The token ID. You may choose an arbitrary value
|
||||
* for the ID
|
||||
*/
|
||||
public function getToken(string $tokenId): CsrfToken;
|
||||
|
||||
/**
|
||||
* Generates a new token value for the given ID.
|
||||
*
|
||||
* This method will generate a new token for the given token ID, independent
|
||||
* of whether a token value previously existed or not. It can be used to
|
||||
* enforce once-only tokens in environments with high security needs.
|
||||
*
|
||||
* @param string $tokenId The token ID. You may choose an arbitrary value
|
||||
* for the ID
|
||||
*/
|
||||
public function refreshToken(string $tokenId): CsrfToken;
|
||||
|
||||
/**
|
||||
* Invalidates the CSRF token with the given ID, if one exists.
|
||||
*
|
||||
* @return string|null Returns the removed token value if one existed, NULL
|
||||
* otherwise
|
||||
*/
|
||||
public function removeToken(string $tokenId): ?string;
|
||||
|
||||
/**
|
||||
* Returns whether the given CSRF token is valid.
|
||||
*/
|
||||
public function isTokenValid(CsrfToken $token): bool;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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\Csrf\Exception;
|
||||
|
||||
use Symfony\Component\Security\Core\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class TokenNotFoundException extends RuntimeException
|
||||
{
|
||||
}
|
||||
19
lib/symfony/security-csrf/LICENSE
Normal file
19
lib/symfony/security-csrf/LICENSE
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2004-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
29
lib/symfony/security-csrf/README.md
Normal file
29
lib/symfony/security-csrf/README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
Security Component - CSRF
|
||||
=========================
|
||||
|
||||
The Security CSRF (cross-site request forgery) component provides a class
|
||||
`CsrfTokenManager` for generating and validating CSRF tokens.
|
||||
|
||||
Sponsor
|
||||
-------
|
||||
|
||||
The Security component for Symfony 6.4 is [backed][1] by [SymfonyCasts][2].
|
||||
|
||||
Learn Symfony faster by watching real projects being built and actively coding
|
||||
along with them. SymfonyCasts bridges that learning gap, bringing you video
|
||||
tutorials and coding challenges. Code on!
|
||||
|
||||
Help Symfony by [sponsoring][3] its development!
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* [Documentation](https://symfony.com/doc/current/components/security.html)
|
||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||
in the [main Symfony repository](https://github.com/symfony/symfony)
|
||||
|
||||
[1]: https://symfony.com/backers
|
||||
[2]: https://symfonycasts.com
|
||||
[3]: https://symfony.com/sponsor
|
||||
@@ -0,0 +1,25 @@
|
||||
<?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\Csrf\TokenGenerator;
|
||||
|
||||
/**
|
||||
* Generates CSRF tokens.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
interface TokenGeneratorInterface
|
||||
{
|
||||
/**
|
||||
* Generates a CSRF token.
|
||||
*/
|
||||
public function generateToken(): string;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?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\Csrf\TokenGenerator;
|
||||
|
||||
/**
|
||||
* Generates CSRF tokens.
|
||||
*
|
||||
* @author Bernhard Schussek <bernhard.schussek@symfony.com>
|
||||
*/
|
||||
class UriSafeTokenGenerator implements TokenGeneratorInterface
|
||||
{
|
||||
private int $entropy;
|
||||
|
||||
/**
|
||||
* Generates URI-safe CSRF tokens.
|
||||
*
|
||||
* @param int $entropy The amount of entropy collected for each token (in bits)
|
||||
*/
|
||||
public function __construct(int $entropy = 256)
|
||||
{
|
||||
if ($entropy <= 7) {
|
||||
throw new \InvalidArgumentException('Entropy should be greater than 7.');
|
||||
}
|
||||
|
||||
$this->entropy = $entropy;
|
||||
}
|
||||
|
||||
public function generateToken(): string
|
||||
{
|
||||
// Generate an URI safe base64 encoded string that does not contain "+",
|
||||
// "/" or "=" which need to be URL encoded and make URLs unnecessarily
|
||||
// longer.
|
||||
$bytes = random_bytes(intdiv($this->entropy, 8));
|
||||
|
||||
return rtrim(strtr(base64_encode($bytes), '+/', '-_'), '=');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?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\Csrf\TokenStorage;
|
||||
|
||||
/**
|
||||
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
|
||||
*/
|
||||
interface ClearableTokenStorageInterface extends TokenStorageInterface
|
||||
{
|
||||
/**
|
||||
* Removes all CSRF tokens.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear();
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<?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\Csrf\TokenStorage;
|
||||
|
||||
use Symfony\Component\Security\Csrf\Exception\TokenNotFoundException;
|
||||
|
||||
/**
|
||||
* Token storage that uses PHP's native session handling.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class NativeSessionTokenStorage implements ClearableTokenStorageInterface
|
||||
{
|
||||
/**
|
||||
* The namespace used to store values in the session.
|
||||
*/
|
||||
public const SESSION_NAMESPACE = '_csrf';
|
||||
|
||||
private bool $sessionStarted = false;
|
||||
private string $namespace;
|
||||
|
||||
/**
|
||||
* Initializes the storage with a session namespace.
|
||||
*
|
||||
* @param string $namespace The namespace under which the token is stored in the session
|
||||
*/
|
||||
public function __construct(string $namespace = self::SESSION_NAMESPACE)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
}
|
||||
|
||||
public function getToken(string $tokenId): string
|
||||
{
|
||||
if (!$this->sessionStarted) {
|
||||
$this->startSession();
|
||||
}
|
||||
|
||||
if (!isset($_SESSION[$this->namespace][$tokenId])) {
|
||||
throw new TokenNotFoundException('The CSRF token with ID '.$tokenId.' does not exist.');
|
||||
}
|
||||
|
||||
return (string) $_SESSION[$this->namespace][$tokenId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setToken(string $tokenId, #[\SensitiveParameter] string $token)
|
||||
{
|
||||
if (!$this->sessionStarted) {
|
||||
$this->startSession();
|
||||
}
|
||||
|
||||
$_SESSION[$this->namespace][$tokenId] = $token;
|
||||
}
|
||||
|
||||
public function hasToken(string $tokenId): bool
|
||||
{
|
||||
if (!$this->sessionStarted) {
|
||||
$this->startSession();
|
||||
}
|
||||
|
||||
return isset($_SESSION[$this->namespace][$tokenId]);
|
||||
}
|
||||
|
||||
public function removeToken(string $tokenId): ?string
|
||||
{
|
||||
if (!$this->sessionStarted) {
|
||||
$this->startSession();
|
||||
}
|
||||
|
||||
if (!isset($_SESSION[$this->namespace][$tokenId])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$token = (string) $_SESSION[$this->namespace][$tokenId];
|
||||
|
||||
unset($_SESSION[$this->namespace][$tokenId]);
|
||||
|
||||
if (!$_SESSION[$this->namespace]) {
|
||||
unset($_SESSION[$this->namespace]);
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
unset($_SESSION[$this->namespace]);
|
||||
}
|
||||
|
||||
private function startSession(): void
|
||||
{
|
||||
if (\PHP_SESSION_NONE === session_status()) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$this->sessionStarted = true;
|
||||
}
|
||||
}
|
||||
112
lib/symfony/security-csrf/TokenStorage/SessionTokenStorage.php
Normal file
112
lib/symfony/security-csrf/TokenStorage/SessionTokenStorage.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?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\Csrf\TokenStorage;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\Security\Csrf\Exception\TokenNotFoundException;
|
||||
|
||||
/**
|
||||
* Token storage that uses a Symfony Session object.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class SessionTokenStorage implements ClearableTokenStorageInterface
|
||||
{
|
||||
/**
|
||||
* The namespace used to store values in the session.
|
||||
*/
|
||||
public const SESSION_NAMESPACE = '_csrf';
|
||||
|
||||
private RequestStack $requestStack;
|
||||
private string $namespace;
|
||||
|
||||
/**
|
||||
* Initializes the storage with a RequestStack object and a session namespace.
|
||||
*
|
||||
* @param string $namespace The namespace under which the token is stored in the requestStack
|
||||
*/
|
||||
public function __construct(RequestStack $requestStack, string $namespace = self::SESSION_NAMESPACE)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
$this->namespace = $namespace;
|
||||
}
|
||||
|
||||
public function getToken(string $tokenId): string
|
||||
{
|
||||
$session = $this->getSession();
|
||||
if (!$session->isStarted()) {
|
||||
$session->start();
|
||||
}
|
||||
|
||||
if (!$session->has($this->namespace.'/'.$tokenId)) {
|
||||
throw new TokenNotFoundException('The CSRF token with ID '.$tokenId.' does not exist.');
|
||||
}
|
||||
|
||||
return (string) $session->get($this->namespace.'/'.$tokenId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setToken(string $tokenId, #[\SensitiveParameter] string $token)
|
||||
{
|
||||
$session = $this->getSession();
|
||||
if (!$session->isStarted()) {
|
||||
$session->start();
|
||||
}
|
||||
|
||||
$session->set($this->namespace.'/'.$tokenId, $token);
|
||||
}
|
||||
|
||||
public function hasToken(string $tokenId): bool
|
||||
{
|
||||
$session = $this->getSession();
|
||||
if (!$session->isStarted()) {
|
||||
$session->start();
|
||||
}
|
||||
|
||||
return $session->has($this->namespace.'/'.$tokenId);
|
||||
}
|
||||
|
||||
public function removeToken(string $tokenId): ?string
|
||||
{
|
||||
$session = $this->getSession();
|
||||
if (!$session->isStarted()) {
|
||||
$session->start();
|
||||
}
|
||||
|
||||
return $session->remove($this->namespace.'/'.$tokenId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$session = $this->getSession();
|
||||
foreach (array_keys($session->all()) as $key) {
|
||||
if (str_starts_with($key, $this->namespace.'/')) {
|
||||
$session->remove($key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws SessionNotFoundException
|
||||
*/
|
||||
private function getSession(): SessionInterface
|
||||
{
|
||||
return $this->requestStack->getSession();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?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\Csrf\TokenStorage;
|
||||
|
||||
/**
|
||||
* Stores CSRF tokens.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
interface TokenStorageInterface
|
||||
{
|
||||
/**
|
||||
* Reads a stored CSRF token.
|
||||
*
|
||||
* @throws \Symfony\Component\Security\Csrf\Exception\TokenNotFoundException If the token ID does not exist
|
||||
*/
|
||||
public function getToken(string $tokenId): string;
|
||||
|
||||
/**
|
||||
* Stores a CSRF token.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setToken(string $tokenId, #[\SensitiveParameter] string $token);
|
||||
|
||||
/**
|
||||
* Removes a CSRF token.
|
||||
*
|
||||
* @return string|null Returns the removed token if one existed, NULL
|
||||
* otherwise
|
||||
*/
|
||||
public function removeToken(string $tokenId): ?string;
|
||||
|
||||
/**
|
||||
* Checks whether a token with the given token ID exists.
|
||||
*/
|
||||
public function hasToken(string $tokenId): bool;
|
||||
}
|
||||
35
lib/symfony/security-csrf/composer.json
Normal file
35
lib/symfony/security-csrf/composer.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "symfony/security-csrf",
|
||||
"type": "library",
|
||||
"description": "Symfony Security Component - CSRF Library",
|
||||
"keywords": [],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"symfony/security-core": "^5.4|^6.0|^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/http-foundation": "^5.4|^6.0|^7.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/http-foundation": "<5.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Component\\Security\\Csrf\\": "" },
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
Reference in New Issue
Block a user