Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як fetch надсилає cookies і CSRF-токен у запитах до Laravel?

Опція credentials визначає, чи надсилає fetch cookies і чи приймає їх з відповіді:

  • 'same-origin' (за замовчуванням) - лише для запитів на той самий домен;
  • 'include' - і для інших доменів (потрібна відповідна CORS-конфігурація сервера);
  • 'omit' - ніколи.

Для звичайного Laravel-застосунку, де сторінки й запити з одного домену, сесійна cookie надсилається автоматично.

CSRF-захист у Laravel перевіряє, що запит, який змінює дані (POST, PUT, PATCH, DELETE), справді надіслано з вашого сайту. Способи передати токен з JavaScript:

1. Заголовок X-CSRF-TOKEN з мета-тегу:

<meta name="csrf-token" content="{{ csrf_token() }}">
await fetch('/orders', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Accept: 'application/json',
    'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
  },
  body: JSON.stringify(order),
});

2. Заголовок X-XSRF-TOKEN з cookie. Laravel ставить cookie XSRF-TOKEN (зашифрований токен, доступний JavaScript). Axios автоматично читає її і додає заголовок для запитів на той самий домен - тому в Laravel-проєктах з axios про CSRF зазвичай не думають. З fetch це треба робити самому.

3. Поле _token у тілі запиту - якщо відправляється FormData з форми, де є @csrf.

Laravel 13 перевіряє ще й джерело запиту. Middleware PreventRequestForgery пропускає запит без токена, якщо браузер надіслав заголовок Sec-Fetch-Site: same-origin. Сучасні браузери додають його самі, а підробити з іншого сайту неможливо. Токен лишається запасним механізмом для старих браузерів і запитів без цього заголовка.

Помилка 419 (Page Expired / CSRF token mismatch) - токен не передано, він застарів (сесія закінчилася, поки сторінка була відкрита) або сесійна cookie не дійшла. Для довго відкритих сторінок варто обробляти 419: оновити токен чи запропонувати перезавантажити сторінку.

SPA на іншому піддомені зі Sanctum:

await fetch('https://api.example.com/sanctum/csrf-cookie', { credentials: 'include' });

await fetch('https://api.example.com/api/orders', {
  method: 'POST',
  credentials: 'include',
  headers: { 'X-XSRF-TOKEN': decodeURIComponent(getCookie('XSRF-TOKEN')), Accept: 'application/json' },
  body: JSON.stringify(order),
});

Потрібні також supports_credentials у config/cors.php, домен SPA у SANCTUM_STATEFUL_DOMAINS і спільний домен сесійних cookies.

Без Accept: application/json Laravel на помилку валідації відповість редиректом, а не JSON з помилками.

Докладніше в документації: fetch()

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання