HTML-формы, отправка данных и CSRF
Формы — главный способ получить данные от пользователя, а защита CSRF и объект Request делают эту работу безопасной и удобной.
Суть: форма отправляет данные методом POST на маршрут, в шаблоне обязательна директива
@csrf, а в контроллере данные читаются через объектRequest.
Любое взаимодействие — регистрация, добавление товара, отправка комментария — это форма. Браузер посылает её содержимое на сервер методом POST, а контроллер должен эти данные принять и обработать. Laravel делает процесс простым и безопасным: объект Request даёт удобный доступ ко всем полям, а встроенная защита CSRF предотвращает подделку запросов.
CSRF (Cross-Site Request Forgery) — это атака, при которой злоумышленник заставляет браузер жертвы отправить запрос от её имени. Laravel защищается токеном: каждая форма должна содержать секретный токен, который проверяется на сервере. Без него запрос отклоняется с ошибкой 419.
Форма и контроллер
{{-- resources/views/products/create.blade.php --}}
<form method="POST" action="/products">
@csrf {{-- обязательный токен защиты --}}
<input type="text" name="name" placeholder="Название">
<input type="number" name="price" placeholder="Цена">
<button type="submit">Сохранить</button>
</form><?php
use Illuminate\Http\Request;
class ProductController extends Controller
{
public function store(Request $request)
{
// чтение данных формы
$name = $request->input('name');
$price = $request->input('price');
// или сразу нужные поля
$data = $request->only(['name', 'price']);
Product::create($data);
return redirect('/products');
}
}Как работает под капотом: защита CSRF
Директива @csrf вставляет в форму скрытое поле с токеном, привязанным к сессии пользователя. Когда форма приходит на сервер, middleware VerifyCsrfToken сравнивает токен из формы с тем, что хранится в сессии. Совпали — запрос проходит; нет — отклоняется. Сторонний сайт не знает токен жертвы, поэтому подделать запрос не может.
ЗАЩИТА CSRF
-----------
1. Сервер кладёт токен в сессию и в форму (@csrf)
2. Пользователь отправляет форму -> токен едет с ней
3. Middleware сверяет: форма.token == сессия.token ?
совпало -> 200 запрос обработан
нет -> 419 отклонено
Чужой сайт токена не знает -> подделка невозможна
Для методов PUT, PATCH, DELETE HTML-формы не поддерживают эти глаголы напрямую, поэтому используется директива @method:
<form method="POST" action="/products/5">
@csrf
@method('DELETE') {{-- подменяет метод на DELETE --}}
<button>Удалить</button>
</form>Смоделируем проверку CSRF-токена на Python.
Попробуй сам ▶
# Проверка CSRF-токена (упрощённо)
session_token = 'secret-abc-123' # токен в сессии пользователя
def handle_request(form_token):
if form_token == session_token:
return '200 OK — данные сохранены'
return '419 — CSRF token mismatch'
print(handle_request('secret-abc-123')) # своя форма
print(handle_request('fake-token')) # чужой сайт
print(handle_request(None)) # токен забыли
Частые ошибки
- Забыть
@csrf. Самая частая причина ошибки 419 — отсутствие токена в форме. - Доверять данным формы. Любой ввод нужно валидировать (следующий урок) — пользователь может прислать что угодно.
- Метод GET для изменения данных. Создание и удаление — это POST/DELETE, а не GET.
Best practices
- Используйте
$request->only([...])или валидированные данные вместо$request->all(). - После успешной обработки делайте
redirect()(паттерн POST-Redirect-GET) — это защищает от повторной отправки. - Для PUT/PATCH/DELETE в формах применяйте
@method.
Объект Request умеет гораздо больше, чем просто читать поля. Метод $request->has('coupon') проверяет наличие поля, $request->filled('coupon') — что оно не пустое, а $request->boolean('subscribe') аккуратно приводит галочку чекбокса к настоящему булеву значению (ведь из формы приходит строка «on» или «1»). Для загрузки файлов есть $request->file('avatar') и метод store(), сохраняющий файл в настроенное хранилище. Важно помнить про идемпотентность: операции, меняющие данные, должны идти через POST/PUT/DELETE, а GET остаётся для безопасного чтения — поисковые роботы и предзагрузка браузера могут «прокликать» GET-ссылки, и если по GET что-то удаляется, последствия будут печальными. Поэтому ссылки-действия (удалить, оформить) всегда оформляют формами с нужным методом, а не обычным тегом ссылки.
Итог: формы отправляют данные методом POST, директива @csrf защищает от подделки, а объект Request даёт удобный доступ к полям. Дальше — как проверять корректность этих данных через валидацию.