Added verification of a token generated outside the engine
https://forkbb.ru/post/211#p211
This commit is contained in:
parent
68abe1e665
commit
8f2886d210
2 changed files with 26 additions and 9 deletions
|
@ -20,8 +20,11 @@ class Csrf
|
||||||
protected ?string $error = null;
|
protected ?string $error = null;
|
||||||
protected int $hashExpiration = 3600;
|
protected int $hashExpiration = 3600;
|
||||||
|
|
||||||
public function __construct(protected Secury $secury, #[SensitiveParameter] protected string $key)
|
public function __construct(
|
||||||
{
|
protected Secury $secury,
|
||||||
|
#[SensitiveParameter] protected string $key,
|
||||||
|
#[SensitiveParameter] protected mixed $externalSalt // сюда и Container может попасть O_o
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,12 +38,24 @@ class Csrf
|
||||||
/**
|
/**
|
||||||
* Возвращает csrf токен
|
* Возвращает csrf токен
|
||||||
*/
|
*/
|
||||||
public function create(string $marker, array $args = [], int|string $time = null): string
|
public function create(string $marker, array $args = [], int|string $time = null, string $type = 's'): string
|
||||||
{
|
{
|
||||||
$marker = $this->argsToStr($marker, $args);
|
$marker = $this->argsToStr($marker, $args);
|
||||||
$time = $time ?: \time();
|
$time = $time ?: \time();
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 's':
|
||||||
return $this->secury->hmac($marker, $time . $this->key) . 's' . $time;
|
return $this->secury->hmac($marker, $time . $this->key) . 's' . $time;
|
||||||
|
case 'x':
|
||||||
|
if (
|
||||||
|
\is_string($this->externalSalt)
|
||||||
|
&& isset($this->externalSalt[9])
|
||||||
|
) {
|
||||||
|
return \hash_hmac('sha1', $marker, $time . $this->externalSalt) . 'x' . $time;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return 'n';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,17 +100,18 @@ class Csrf
|
||||||
|
|
||||||
if (
|
if (
|
||||||
\is_string($token)
|
\is_string($token)
|
||||||
&& \preg_match('%(e|s)(\d+)$%D', $token, $matches)
|
&& \preg_match('%(e|s|x)(\d+)$%D', $token, $matches)
|
||||||
) {
|
) {
|
||||||
switch ($matches[1]) {
|
switch ($matches[1]) {
|
||||||
// токен
|
// токен
|
||||||
case 's':
|
case 's':
|
||||||
|
case 'x':
|
||||||
if ($matches[2] + ($lifetime ?? self::TOKEN_LIFETIME) < $now) {
|
if ($matches[2] + ($lifetime ?? self::TOKEN_LIFETIME) < $now) {
|
||||||
// просрочен
|
// просрочен
|
||||||
$this->error = 'Expired token';
|
$this->error = 'Expired token';
|
||||||
} elseif (
|
} elseif (
|
||||||
$matches[2] + 0 <= $now
|
$matches[2] + 0 <= $now
|
||||||
&& \hash_equals($this->create($marker, $args, $matches[2]), $token)
|
&& \hash_equals($this->create($marker, $args, $matches[2], $matches[1]), $token)
|
||||||
) {
|
) {
|
||||||
$this->error = null;
|
$this->error = null;
|
||||||
$result = true;
|
$result = true;
|
||||||
|
|
|
@ -184,6 +184,7 @@ return [
|
||||||
'class' => \ForkBB\Core\Csrf::class,
|
'class' => \ForkBB\Core\Csrf::class,
|
||||||
'Secury' => '@Secury',
|
'Secury' => '@Secury',
|
||||||
'key' => '%user.password%%user.ip%%user.id%%BASE_URL%',
|
'key' => '%user.password%%user.ip%%user.id%%BASE_URL%',
|
||||||
|
'extSalt' => '',
|
||||||
],
|
],
|
||||||
'Online' => \ForkBB\Models\Online\Online::class,
|
'Online' => \ForkBB\Models\Online\Online::class,
|
||||||
'Cookie' => [
|
'Cookie' => [
|
||||||
|
|
Loading…
Reference in a new issue