Пояснено заголовок Access-Control-Allow-Origin - на прикладі CORS

Часто під час виклику API ви можете побачити на консолі помилку, яка виглядає так:

 Access to fetch at '//somesite.com' from origin '//yoursite.com' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value that is not equal to the supplied origin 

У цій публікації ми збираємось дізнатись, чому трапляється ця помилка та як ви можете її виправити.

Що таке Access-Control-Allow-Originзаголовок?

Access-Control-Allow-Originє заголовком CORS. CORS, або Cross Origin Resource Sharing, - це механізм для браузерів дозволяти веб-сайту, що працює у джерелі A, запитувати ресурси з джерела B.

Походження - це не просто ім'я хосту, а комбінація порту, імені хосту та схеми, наприклад - //mysite.example.com:8080/

Ось приклад того, як це вступає в дію -

  1. У мене є походження A: //mysite.comі я хочу , щоб отримати ресурси від походження B: //yoursite.com.
  2. Щоб захистити вашу безпеку, веб-переглядач не дозволить мені отримувати доступ до ресурсів із вашого веб-сайту і заблокує мій запит.
  3. Для того, щоб дозволити джерелу A отримати доступ до ваших ресурсів, ваше джерело B повинно повідомити браузеру, що мені добре отримувати ресурси від вашого джерела.

Ось приклад із мережі розробників Mozilla, який дуже добре пояснює це:

За допомогою CORS браузери дозволяють джерелам обмінюватися ресурсами між собою.

Є декілька заголовків, які дозволяють розподіляти ресурси між джерелами, але головним є Access-Control-Allow-Origin. Це повідомляє браузеру, яким джерелам дозволено отримувати запити від цього сервера.

Кому потрібно встановити Access-Control-Allow-Origin?

Щоб зрозуміти, кому потрібно встановити цей заголовок, розглянемо такий сценарій: Ви переглядаєте веб-сайт, який використовується для перегляду та прослуховування пісень. Веб-сайт намагається зловмисно підключитися до вашого банку у фоновому режимі.

Отже, хто має найвищу здатність запобігти крадіжці цих зловмисних веб-сайтів у банку? Банк! Отже, банку потрібно буде захистити свої ресурси, встановивши Access-Control-Allow-Originзаголовок як частину відповіді.

Тільки пам’ятайте: джерелу, відповідальному за обслуговування ресурсів, потрібно буде встановити цей заголовок.

Як використовувати і коли передавати цей заголовок

Ось приклад значень, які ви можете встановити:

  1. Access-Control-Allow-Origin : * : Дозволяє будь-яке походження.
  2. Access-Control-Allow-Origin : //mysite.com : Дозволити запити лише з mysite.com.

Побачте це в дії

Давайте розглянемо приклад. Ви можете перевірити цей код на моєму репозиторії GitHub.

Ми збираємося створити сервер з початком А, //localhost:8000який надішле рядок Hellos до apiкінцевої точки. Ми збираємось зателефонувати з цією кінцевою точкою, створивши клієнта з джерела B, //localhost:3000а потім використати fetch для запиту ресурсу. Ми очікуємо побачити рядок, Helloпереданий початком A на консолі браузера джерела B.

Скажімо, у нас є початок, //localhost:8000який обслуговує цей ресурс у /apiкінцевій точці. Сервер надсилає відповідь із заголовком Access-Control-Allow-Origin.

const express = require("express"); const app = express(); const port = process.env.SERVER_PORT || 8000; // Add Access Control Allow Origin headers app.use((req, res, next) => { res.setHeader("Access-Control-Allow-Origin", "//yoursite.com"); res.header( "Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept" ); next(); }); app.get("/api", (req, res) => { res.json("Hello"); }); app.listen(port, () => console.log(`Listening on port ${port}`)); 

На стороні клієнта ви можете викликати цю кінцеву точку, зателефонувавши fetchтак:

fetch('//localhost:8000/api') .then(res => res.json()) .then(res => console.log(res)); 

Тепер відкрийте консоль браузера, щоб побачити результат.

Оскільки в даний момент заголовок налаштовано на доступ лише з //yoursite.com, браузер заблокує доступ до ресурсу, і ви побачите помилку на консолі.

Тепер, щоб це виправити, змініть заголовки на таке:

 res.setHeader("Access-Control-Allow-Origin", "*"); 

Перевірте консоль браузера, і тепер ви зможете побачити рядок Hello.

Вас цікавлять інші підручники та JSBytes від мене? Підпишіться на мій бюлетень.