Разработка на PHP: Как реализовать метод защиты от повторной отправки формы (Double Submit Cookie или CSRF Token), чтобы избежать дублей в базе данных?
Повторная отправка формы (double submit) — распространённая проблема в веб-разработке, которая приводит к дублированию записей в базе данных. Рассмотрим два основных подхода к её решению на PHP.
## 1. CSRF Token (одноразовый токен)
Это наиболее надёжный метод. Суть: при каждой загрузке формы генерируется уникальный токен, который хранится в сессии и передаётся скрытым полем. После успешной обработки токен уничтожается.
**Генерация токена:**
php
session_start();
if (empty($_SESSION[‘csrf_token’])) {
$_SESSION[‘csrf_token’] = bin2hex(random_bytes(32));
}
**Вставка в форму:**
html
<input type="hidden" name="csrf_token" value="»>
**Проверка при обработке:**
php
session_start();
if (!isset($_POST[‘csrf_token’]) || $_POST[‘csrf_token’] !== $_SESSION[‘csrf_token’]) {
die(‘Недействительный токен. Повторная отправка запрещена.’);
}
// Инвалидируем токен после использования
unset($_SESSION[‘csrf_token’]);
// Далее — запись в базу данных
После успешной обработки выполните редирект (паттерн PRG — Post/Redirect/Get), чтобы предотвратить повторную отправку при обновлении страницы:
php
header(‘Location: /success.php’);
exit;
## 2. Double Submit Cookie
Метод основан на том, что злоумышленник не может читать куки другого домена. Токен одновременно записывается в куку и в скрытое поле формы. При обработке сервер сравнивает их.
php
// Установка куки и поля формы
$token = bin2hex(random_bytes(32));
setcookie(‘csrf_cookie’, $token, [
‘httponly’ => true,
‘samesite’ => ‘Strict’,
‘secure’ => true
]);
html
<input type="hidden" name="csrf_field" value="»>
**Проверка:**
php
if (!isset($_COOKIE[‘csrf_cookie’], $_POST[‘csrf_field’])
|| !hash_equals($_COOKIE[‘csrf_cookie’], $_POST[‘csrf_field’])) {
die(‘Ошибка проверки токена.’);
}
## 3. Дополнительная защита на уровне БД
Даже при использовании токенов рекомендуется добавить уникальный индекс на критичные поля в таблице:
sql
ALTER TABLE orders ADD UNIQUE INDEX idx_unique_order (user_id, product_id, created_at);
Или использовать `INSERT IGNORE` / `ON DUPLICATE KEY UPDATE` в MySQL для атомарной защиты.
## Итог
— **CSRF Token** — лучший выбор для большинства форм: надёжен, прост в реализации.
— **Double Submit Cookie** — подходит для stateless-архитектур (API, микросервисы).
— **PRG-паттерн** обязателен после любой успешной обработки POST-запроса.
— **Уникальные индексы** в БД — последний рубеж защиты от дублей.
