app.A.comfetch('B/api')api.B.comA-C-A-O: A.comOPTIONS preflightCORS allow → JS may readrequest always reaches server; response visibility is gated

Спільне використання ресурсів між джерелами

11 хв. читанняВеб-технології

CORS — одна з найбільш заплутаних веб-технологій, оскільки вона вказує браузерам, що дозволяти, а не блокує атаки на сервер. Коли ви зрозумієте цю різницю, правила набудуть сенсу. CORS дозволяє серверам вибірково надавати дозволи між джерелами; за замовчуванням політика того самого походження – ні.

Повний текст статті подано англійською мовою нижче.

Cross-Origin Resource Sharing (CORS) — це механізм браузера, який дозволяє серверу оголошувати, яким іншим джерелам дозволено доступ до його відповідей. У поєднанні з політикою того самого джерела (за замовчуванням у браузері встановлено значення «не дозволяти одному джерелу читати відповіді іншого»), CORS забезпечує механізм вибіркової релаксації.

Спершу політика того самого джерела

За замовчуванням браузери забезпечують, щоб JavaScript, запущений на джерелі A, не міг читати відповіді з джерела B. Це та сама політика джерела. «Походження» означає схему + хост + порт; https://a.example.com і https://b.example.com мають різне походження.

Ця політика забороняє JavaScript одного сайту читати ваші дані на іншому сайті, де ви ввійшли в систему. Без неї кожен сайт, який ви відвідуєте, міг би читати ваш Gmail, ваш банк, ваші приватні сховища — ваш браузер автоматично надсилає файли cookie, тому адресат із задоволенням відповість, і JS зловмисника побачить відповідь.

Що додає CORS

Багато законних випадків використання вимагають перехресного читання — шрифти з CDN, виклики API з інтерфейсу до сервера в іншому домені, вбудовані віджети соціальних мереж. CORS дозволяє серверу-відповідачу явно сказати «так, це інше джерело може читати мої відповіді».

Сервер включає заголовок Access-Control-Allow-Origin у свою відповідь. Браузер перевіряє: якщо джерело запиту відповідає значенню (або це символ підстановки *), відповідь піддається JavaScript. Якщо ні, браузер блокує читання JavaScript. Запит все ще пішов, сервер все ще отримав і обробив його — лише видимість JavaScript обмежена.

Прості запити проти попередніх запитів

Для «простих» запитів (GET, HEAD, POST з основними типами вмісту) браузер надсилає запит і перевіряє CORS на відповідь. Якщо CORS не дозволяє, JavaScript не може його прочитати.

Для «складних» запитів (PUT, DELETE, користувацькі заголовки, тип вмісту JSON) браузер спочатку надсилає запит preflight OPTIONS із запитом «чи може origin X надіслати вам цей запит?» Сервер відповідає дозволеними методами та заголовками. Лише якщо схвалено, браузер надсилає фактичний запит.

// Preflight
ПАРАМЕТРИ /api/users HTTP/1.1
Походження: https://app.example.com
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: авторизація

// Відповідь сервера
HTTP/1.1 204 Немає вмісту
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: DELETE, GET, POST
Access-Control-Allow-Headers: авторизація, Content-Type
Access-Control-Max-Age: 86400

Попередня перевірка запобігає надсиланню браузерами складних запитів на зміну стану на сервери, які їх не очікують — базовий захист навіть від неправильно налаштованих серверів.

Credentials і CORS

Cookie і заголовки автентифікації HTTP ("облікові дані") за умовчанням не надсилаються за запитами між джерелами. Щоб включити їх, JavaScript має запитати:

fetch('https://api.example.com/data', { credentials: 'include' })

І сервер має відповісти Access-Control-Allow-Credentials: true і конкретне джерело (не символ підстановки *) у Access-Control-Allow-Origin. Це типова проблема: Access-Control-Allow-Origin: * + облікові дані = нічого не працює.

Поширені непорозуміння CORS

  • CORS не є функцією безпеки для серверів. Запит досягає сервера незалежно від CORS. Браузер блокує JavaScript від читання відповіді. Сервери все одно повинні пройти автентифікацію та авторизуватися.
  • CORS не застосовується до всіх запитів. Запити з однаковим джерелом не запускають CORS. Запити між серверами також не підходять. Перехресне походження між браузером і сервером — це єдине місце, де живе CORS.
  • Знак узагальнення * небезпечний у поєднанні з файлами cookie. У багатьох посібниках пропонується Access-Control-Allow-Origin: * як швидке вирішення проблеми. Для загальнодоступних API без облікових даних добре. Для всього, що має автентифікацію, зламано. Помилки
  • CORS є проблемами на стороні сервера. Коли ви бачите помилки CORS на консолі браузера, виправлення відбувається на сервері, який відповідає, а не на коді запиту.

CORS проти CSRF

Легко заплутатися. CORS контролює те, що браузер надає JavaScript. CSRF (див. нашу статтю CSRF ) стосується того, чи браузер взагалі надсилає запит. CORS не перешкоджає CSRF — запит можна надіслати й обробити, навіть якщо JavaScript не бачить відповіді.

Для API зі зміною стану, які використовують файли cookie, все ще потрібні маркери CSRF або файли cookie SameSite. CORS не замінює їх.

Кеш перед друком

Відповіді перед друком можна кешувати через Access-Control-Max-Age. Довгий максимальний вік (24+ години) зменшує накладні витрати — кожна окрема комбінація (метод, URL-адреса, заголовки) не перевіряється повторно до завершення терміну дії. Короткий максимальний вік може призвести до значної затримки.

Загальні шаблони CORS у 2026

  • Загальнодоступні API: Access-Control-Allow-Origin: * для кінцевих точок без authentication.
  • Authenticated APIs: echo back the calling Origin, якщо він у дозволеному списку, з Access-Control-Allow-Credentials: true.
  • SaaS APIs: для кожного клієнта дозволені списки, налаштовані замовником.
  • JS Доставка SDK: статичні файли із широким CORS, часто шаблон загальнодоступного API.

Часті запитання

Чому моє отримання не вдається через помилку CORS?
Сервер, який ви викликаєте, не містить відповідного заголовка Access-Control-Allow-Origin для вашого джерела. Або сервер має бути налаштований, щоб дозволити вам, або вам потрібно викликати його з того самого джерела (зазвичай через серверний проксі).
Чи можу я обійти CORS як розробник?
З вашого власного коду у веб-переглядачі ні — це примусово виконує браузер. З вашого власного сервера (бекенд-код), так, оскільки CORS не застосовується до запитів між серверами. Загальним обхідним шляхом є бекенд-проксі: ваш інтерфейс викликає ваш бекенд; ваш сервер викликає сторонній API.
Чи захищає CORS мій API?
Не прямо. API доступний незалежно від CORS — браузер все одно надсилає запит. Захист полягає в тому, що JavaScript на інших сайтах не може читати відповіді. Щоб фактично захистити API, використовуйте автентифікацію та авторизацію на сервері.
Чи варто використовувати Access-Control-Allow-Origin: *?
Лише для публічних API, які не приймають облікові дані. Для всього, що містить файли cookie або заголовки авторизації, використовуйте конкретні джерела або відтворюйте виклик Origin (з перевіркою). Браузери забороняють використовувати символ підстановки + облікові дані.
Чому CORS перед друком виконує лише деякі запити?
Прості запити (GET, HEAD, POST із основними типами вмісту та без користувальницьких заголовків) виключаються — вони еквівалентні тому, що могли робити HTML-форми до появи CORS. Складні запити не мають аналога HTML-форми, тому вони перед друком, щоб дати серверу можливість відхилити до будь-якої зміни стану.
Пояснення CORS: як браузери вирішують, чи дозволені запити між джерелами