OpenXE/classes/Components/Http/Session/CsrfTokenManager.php
2021-05-21 08:49:41 +02:00

115 lines
2.4 KiB
PHP

<?php
namespace Xentral\Components\Http\Session;
use Xentral\Components\Http\Exception\CsrfTokenException;
use Xentral\Components\Http\Exception\InvalidArgumentException;
use Xentral\Components\Util\StringUtil;
final class CsrfTokenManager
{
/** @var int CSRF_TOKEN_LENGTH */
const CSRF_TOKEN_LENGTH = 32;
/** @var array $tokenData */
private $tokenData;
/**
* @param array $tokenData
*/
public function __construct($tokenData = [])
{
$this->tokenData = $tokenData;
}
/**
* @param string $key
* @param string $value
* @param bool $remove
*
* @return bool
*/
public function isTokenValid($key, $value, $remove = true)
{
$this->ensureTokenKeyFormat($key);
$valid = false;
if (array_key_exists($key, $this->tokenData) && $this->tokenData[$key] === $value) {
$valid = true;
}
if ($valid === true && $remove === true) {
$this->removeToken($key);
}
return $valid;
}
/**
* @param $key
*
* @throws CsrfTokenException
*
* @return string
*/
public function createToken($key)
{
$this->ensureTokenKeyFormat($key);
$token = StringUtil::random(self::CSRF_TOKEN_LENGTH, true);
$this->tokenData[$key] = $token;
if (strlen($token) < self::CSRF_TOKEN_LENGTH) {
throw new CsrfTokenException('Could not create CSRF token.');
}
return $token;
}
/**
* @param $key
*
* @return void
*/
public function removeToken($key)
{
$this->ensureTokenKeyFormat($key);
unset($this->tokenData[$key]);
}
/**
* @param string $key
*
* @throws InvalidArgumentException
*
* @return string
*/
public function refreshToken($key)
{
$this->ensureTokenKeyFormat($key);
$this->removeToken($key);
return $this->createToken($key);
}
/**
* @param $target
*
* @return void
*/
public function dumpTokens(&$target)
{
$target = $this->tokenData;
}
/**
* @param string $key
*
* @throws InvalidArgumentException
*
* @return void
*/
private function ensureTokenKeyFormat($key)
{
if (!preg_match('/^[a-z][a-z0-9_]*$/', $key)) {
throw new InvalidArgumentException('Invalid token key format.');
}
}
}