feat: implement global autoresponder plugin
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
final class CsrfGuard
|
||||
{
|
||||
public function __construct(private string $secret, private string $username, private string $sessionId)
|
||||
{
|
||||
$this->sessionId = $this->sessionId !== '' ? $this->sessionId : 'no_session';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{ts:int,sid:string,token:string}
|
||||
*/
|
||||
public function issue(string $intent): array
|
||||
{
|
||||
$ts = time();
|
||||
return ['ts' => $ts, 'sid' => $this->sessionId, 'token' => $this->buildToken($intent, $ts, $this->sessionId)];
|
||||
}
|
||||
|
||||
public function validate(string $intent, string $timestamp, string $token, int $ttl = 3600, string $sessionHint = ''): bool
|
||||
{
|
||||
if (!preg_match('/^[0-9]{1,20}$/', $timestamp)) {
|
||||
return false;
|
||||
}
|
||||
$ts = (int)$timestamp;
|
||||
$now = time();
|
||||
if ($ts <= 0 || $ts > $now + 30 || $now - $ts > $ttl) {
|
||||
return false;
|
||||
}
|
||||
$sids = array_values(array_unique(array_filter([$sessionHint, $this->sessionId, 'no_session'], static fn ($v): bool => $v !== '')));
|
||||
foreach ($sids as $sid) {
|
||||
if (hash_equals($this->buildToken($intent, $ts, $sid), trim($token))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function buildToken(string $intent, int $timestamp, string $sid): string
|
||||
{
|
||||
return hash_hmac('sha256', implode('|', [$this->username, $sid, $intent, (string)$timestamp]), $this->secret);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user