chore: восстановление репозитория из снапшота v0.3.1
Прежняя git-история утрачена при переносе проекта на машину владельца (снапшот без .git). Хэши коммитов в docs/reports/* относятся к утраченной истории. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
commit
1c85091186
184 changed files with 33303 additions and 0 deletions
54
server/lib/ratelimit.php
Normal file
54
server/lib/ratelimit.php
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Rate limiting по IP через таблицу rate_log.
|
||||
* Контракт: register/login — 10 попыток за 10 минут на IP → 429
|
||||
* {"error":"rate_limited"}; проверка ДО проверки пароля; успешный login
|
||||
* чистит счётчик ip+action. Prepared statements везде.
|
||||
* Этап 8.1: reset_request — 5 за 10 минут, reset_confirm — 10 за 10 минут.
|
||||
*/
|
||||
|
||||
const GOLEARN_RATE_MAX = 10;
|
||||
const GOLEARN_RATE_WINDOW = 600; // 10 минут, секунд
|
||||
|
||||
const GOLEARN_RATE_MAX_RESET_REQUEST = 5;
|
||||
const GOLEARN_RATE_MAX_RESET_CONFIRM = 10;
|
||||
|
||||
/**
|
||||
* 429, если попыток ip+action за окно уже >= лимита.
|
||||
* Вызывается ДО записи текущей попытки и до проверки пароля.
|
||||
*/
|
||||
function rate_check(
|
||||
PDO $pdo,
|
||||
string $ip,
|
||||
string $action,
|
||||
int $max = GOLEARN_RATE_MAX
|
||||
): void {
|
||||
$stmt = $pdo->prepare(
|
||||
'SELECT COUNT(*) AS n FROM rate_log
|
||||
WHERE ip = ? AND action = ? AND ts > ?'
|
||||
);
|
||||
$stmt->execute([$ip, $action, time() - GOLEARN_RATE_WINDOW]);
|
||||
$row = $stmt->fetch();
|
||||
if (is_array($row) && (int)$row['n'] >= $max) {
|
||||
error_out(429, 'rate_limited');
|
||||
}
|
||||
}
|
||||
|
||||
/** Записать попытку (после прохождения rate_check). */
|
||||
function rate_record(PDO $pdo, string $ip, string $action): void
|
||||
{
|
||||
$stmt = $pdo->prepare(
|
||||
'INSERT INTO rate_log (ip, action, ts) VALUES (?, ?, ?)'
|
||||
);
|
||||
$stmt->execute([$ip, $action, time()]);
|
||||
}
|
||||
|
||||
/** Сбросить счётчик ip+action (успешный login). */
|
||||
function rate_clear(PDO $pdo, string $ip, string $action): void
|
||||
{
|
||||
$stmt = $pdo->prepare('DELETE FROM rate_log WHERE ip = ? AND action = ?');
|
||||
$stmt->execute([$ip, $action]);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue