Повний посібник із вирішення проблеми з надсиланням файлів cookie у міждоменних запитах (CORS)
Якщо ви зіткнулися зі сценарієм, коли сервер правильно встановлює файл cookie (видно у відповіді браузера), але в наступних запитах браузер не повертає цей файл cookie на сервер, цей посібник для вас. Ця проблема майже завжди виникає, коли фронтенд і бекенд вашого проекту знаходяться на двох різних доменах або портах — наприклад, фронтенд на app.example.com, а API на api.example.com.
Чому це відбувається?
Сучасні браузери застосовують дві суворі політики безпеки для запобігання CSRF-атак і викрадення сесій:
- Політика CORS: За замовчуванням браузер не дозволяє міждоменним запитам включати облікові дані (наприклад, файли cookie), якщо сервер явно не дозволяє це.
- Політика SameSite: Починаючи з Chrome 80, файли cookie за замовчуванням обробляються з поведінкою
SameSite=Lax, що означає, що вони не будуть надсилатися в міждоменних запитах, якщо їх явно не визначено зSameSite=None.
Важливо зазначити, що для вирішення цієї проблеми і клієнтська, і серверна сторони мають бути правильно налаштовані. Лише зміна однієї сторони недостатня.
Крок 1: Правильне налаштування сервера
Три золоті правила на стороні сервера
Правило 1 — Увімкнення облікових даних: Заголовок відповіді сервера повинен містити наступне значення:
Access-Control-Allow-Credentials: true
Правило 2 — Без підстановочних знаків: Коли облікові дані ввімкнено, ви не можете використовувати підстановочний знак * у заголовку Access-Control-Allow-Origin. Ви повинні точно вказати повну адресу домену фронтенду:
Access-Control-Allow-Origin: https://app.example.com
Правило 3 — Атрибути файлу cookie: Файл cookie має бути встановлений з двома атрибутами: SameSite=None та Secure. Без цих двох атрибутів браузер збереже файл cookie, але ніколи не надішле його в міждоменних запитах.
Приклад коду в Node.js (Express)
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors({
origin: 'https://app.example.com', // Точний домен фронтенду, без /
credentials: true
}));
app.post('/login', (req, res) => {
res.cookie('session_token', 'abc123', {
httpOnly: true, // Запобігає доступу JavaScript до файлу cookie
secure: true, // Надсилається лише через HTTPS
sameSite: 'none', // Дозволяє надсилання в міждоменних запитах
maxAge: 24 * 60 * 60 * 1000
});
res.json({ message: 'Вхід виконано успішно' });
});
Приклад коду в PHP
<?php
// Вкажіть точний домен фронтенду, не *
header("Access-Control-Allow-Origin: https://app.example.com");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
// Відповідь на попередній запит
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
// Встановлення файлу cookie з необхідними атрибутами
setcookie('session_token', 'abc123', [
'expires' => time() + 86400,
'path' => '/',
'secure' => true, // Обов'язково
'httponly' => true,
'samesite' => 'None' // Обов'язково для міждоменних запитів
]);
Примітка: Якщо ви використовуєте Laravel, встановіть supports_credentials на true у файлі config/cors.php і додайте домен фронтенду до масиву allowed_origins.
Крок 2: Правильне налаштування клієнта (фронтенду)
Навіть при повному налаштуванні сервера браузер все одно не надсилатиме файли cookie, якщо ви явно не оголосите на стороні клієнта, що цей запит "з обліковими даними".
Використання Fetch API
fetch('https://api.example.com/user/profile', {
method: 'GET',
credentials: 'include' // Цей рядок є ключем до вирішення проблеми
})
.then(res => res.json())
.then(data => console.log(data));
Використання Axios
// Для конкретного запиту
axios.get('https://api.example.com/user/profile', {
withCredentials: true
});
// Або глобально для всього проекту
axios.defaults.withCredentials = true;
Контрольний список для усунення несправностей
Якщо проблема зберігається після застосування вищезазначеного, перевірте ці пункти по порядку:
- ✅ Чи обидві сторони на HTTPS? Атрибут
Secureозначає, що файл cookie працює лише через зашифровані з'єднання. Якщо ваш сайт на HTTP, браузер не прийме файл cookie. (Виняток: середовище розробки наlocalhost) - ✅ Чи точна адреса Origin? Адреса
Access-Control-Allow-Originповинна точно збігатися з URL, який ви бачите в браузері. Навіть різниця вwwwабо завершальна коса риска/спричинить помилку. - ✅ Чи успішний запит OPTIONS? На вкладці Network в інструментах розробника браузера перевірте попередній запит (з методом OPTIONS). Цей запит має бути відповідей з кодом 200 або 204 і правильними заголовками CORS.
- ✅ Чи збережено файл cookie? У браузері перейдіть до DevTools ← Application ← Cookies і переконайтеся, що файл cookie збережено з атрибутами
SecureтаSameSite=None. - ✅ Чи є проксі або проміжний брандмауер? Іноді Cloudflare або веб-сервери, такі як Nginx, перезаписують заголовки. Перевірте також їхню конфігурацію.
Резюме
Надсилання файлів cookie в міждоменних запитах вимагає координації трьох факторів: сервер з Access-Control-Allow-Credentials: true і точним Origin, файл cookie з атрибутами SameSite=None; Secure і клієнт з активацією credentials: 'include' або withCredentials: true. Дотримуючись цих трьох пунктів, проблема буде повністю вирішена.
Надійна інфраструктура, спокій для розробників
Правильна реалізація CORS та управління файлами cookie — це лише частина історії; інфраструктура, на якій працює ваш проект, також відіграє вирішальну роль у стабільності та безпеці сервісу:
Radib Hosting — Високошвидкісний веб-хостинг з повною підтримкою безкоштовного SSL та стандартною конфігурацією заголовків; ідеальний вибір для хостингу фронтенду та бекенду ваших проектів.
Radib Virtual Server — Якщо ваш проект вимагає повного доступу, виділених ресурсів і свободи в налаштуванні веб-сервера (Nginx/Apache), віртуальні сервери Radib з потужним обладнанням та стабільною мережею є найкращим вибором для професійних API.
Radib Debugging and Security Services — Якщо ви стикаєтеся зі складними помилками CORS, проблемами автентифікації або викликами безпеки, технічна команда Radib з глибоким досвідом усунення несправностей і забезпечення безпеки веб-додатків готова допомогти вам вирішити проблему від кореня.


