Де у запиті передаються куки




Де у запиті передаються куки



Куки, document.cookie

Cookies – це невеликі рядки даних, які зберігаються безпосередньо у браузері. Вони є частиною протоколу HTTP, визначеного в специфікації RFC 6265.

Куки зазвичай встановлюються веб-сервером за допомогою заголовка Set-Cookie. Потім браузер автоматично додаватиме їх у (майже) кожен запит на той же домен за допомогою заголовка Cookie .

Один з найчастіших випадків використання cookie – це аутентифікація:

  1. При вході на сайт сервер надсилає у відповідь HTTP-заголовок Set-Cookie для того, щоб встановити cookie із спеціальним унікальним ідентифікатором сесії («session identifier»).
  2. Під час наступного запиту до цього домену браузер посилає на сервер HTTP-заголовок Cookie .
  3. Таким чином сервер розуміє, хто зробив запит.

Ми також можемо отримати доступ до cookie безпосередньо з браузера, використовуючи властивість document.cookie.

Кукі мають безліч особливостей і тонкощів у використанні, і в цьому розділі ми докладно з ними розберемося.

Читання з document.cookie

Чи зберігає ваш браузер якісь куки з цього сайту? Подивимося:

// На javascript.info ми використовуємо сервіс Google Analytics для збору статистики, // тому якісь куки мають бути alert(document.cookie); //cookie1=value1; cookie2=value2;.

Значення document.cookie складається з пар ключ = значення , розділених ; . Кожна пара є окремим куки.

Щоб знайти певне куки, достатньо розбити рядок з document.cookie по ; , а потім знайти потрібний ключ. І тому ми можемо використовувати як регулярні висловлювання, і функції обробки масивів.

Залишимо це завдання читачеві для самостійного виконання. Крім того, в кінці цього розділу ви знайдете корисні функції для роботи з cookie.

Запис у document.cookie

Ми можемо писати в document.cookie. Але це не просто властивість даних, а аксесор (гетер/сетер). Привласнення щодо нього обробляється особливим чином.

Запис у document.cookie оновить лише згадані в ній куки, але при цьому не торкнеться всіх інших.

Наприклад, цей виклик встановить cookie з ім'ям user і значенням John :

document.cookie="user=John"; // оновлюємо лише куки з ім'ям 'user' alert(document.cookie); // показуємо всі куки

Якщо ви запустите цей код, то, швидше за все, побачите безліч куки. Це відбувається тому, що операція document.cookie = перезапише не всі куки, а лише куки з вищезгаданим ім'ям user .

Технічно, і ім'я та значення cookie можуть складатися з будь-яких символів, для правильного форматування слід використовувати вбудовану функцію encodeURIComponent :

// Спеціальні символи (пробіли), потрібно кодування let name = "my name"; let value = "John Smith" // кодує в my%20name=John%20Smith document.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value); alert(document.cookie); //. ; my%20name=John%20Smith

Існує кілька обмежень:

  • Після encodeURIComponent пара name=value не повинна займати більше 4Кб. Таким чином, ми не можемо зберігати в кукі великі дані.
  • Загальна кількість cookie на один домен обмежується приблизно 20+. Точне обмеження залежить від конкретного браузера.

У cookie є ряд налаштувань, багато з яких важливі і повинні бути встановлені.

Ці налаштування вказуються після пари ключ = значення та відокремлені один від одного роздільником ; , Ось так:

document.cookie = "user=John; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT"

path

URL-префікс шляху, cookie будуть доступні для сторінок під цим шляхом. Має бути абсолютним. За промовчанням використовується поточний шлях.

Якщо cookie встановлено з path=/admin , воно буде доступне на сторінках /admin та /admin/something , але не на сторінках /home або /adminpage .

Як правило, вказують як шлях корінь path=/ , щоб наше куки було доступне на всіх сторінках сайту.

domain

Домен визначає, де доступний файл cookie. Однак на практиці існують певні обмеження. Ми не можемо вказати тут будь-який домен.

Немає ніякого способу дозволити доступ до файлів cookie з іншого домену 2-го рівня, тому other.com ніколи не отримає cookie, встановлений за адресою site.com.

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

За замовчуванням куки доступні лише тому домену, що його встановив.

Будь ласка, зверніть увагу, що файл cookie за замовчуванням також не передається піддомену, наприклад forum.site.com .

// якщо ми встановимо файл cookie на веб-сайті site.com. document.cookie = "user=John" // . ми побачимо його на forum.site.com alert(document.cookie); // ні user

…Але це можна змінити. Якщо ми хочемо дозволити піддоменам типу forum.site.com отримувати куки, встановлені на site.com, це можливо.

Щоб це сталося, при установці файлу куки в site.com ми повинні явно встановити параметр domain для кореневого домену: domain=site.com . Після цього всі піддомени побачать такий файл cookie.

// перебуваючи на сторінці site.com // зробимо куки доступним для всіх піддоменів *.site.com: document.cookie = "user=John; domain=site.com" // пізніше // на forum.site.com alert( document.cookie); // є куки user=John

З історичних причин установка domain=.site.com (з точкою перед site.com) також працює і дозволяє доступ до cookie для піддоменів.Це старий запис, але можна використовувати його, якщо потрібно, щоб підтримувалися дуже старі браузери.

Таким чином, опція domain дозволяє нам дозволити доступ до cookie для піддоменів.

expires, max-age

За замовчуванням, якщо куки не мають жодного з цих параметрів, вони видаляться при закритті браузера. Такі куки називаються сесійними ("session cookies").

Щоб допомогти cookie «пережити» закриття браузера, ми можемо встановити значення опцій expires або max-age.

Дата закінчення терміну дії cookie, коли браузер видалить його автоматично.

Дата має бути точно у цьому форматі, у часовій зоні GMT. Ми можемо використовувати date.toUTCString для отримання правильної дати. Наприклад, ми можемо встановити термін дії cookie на 1 день.

// +1 день з поточної дати let date = new Date(Date.now() + 86400e3); date = date.toUTCString(); document.cookie = "user=John; expires=" + date;

Якщо ми встановимо в expires минулу дату, то кукі буде видалено.

Альтернатива expires визначає термін дії cookie в секундах з поточного моменту.

Якщо задано нуль або негативне значення, то куки буде видалено:

// куки буде видалено через 1 годину document.cookie = "user=John; max-age=3600"; // видалимо куки (термін дії закінчується зараз) document.cookie = "user=John; max-age=0";

secure

Куки слід передавати лише за протоколом HTTPS.

За промовчанням куки, встановлені сайтом http://site.com, також будуть доступні на сайті https://site.com і навпаки.

Тобто, куки, за замовчуванням, спираються на доменне ім'я, вони не звертають уваги на протоколи.

З цією настройкою, якщо куки буде встановлено на сайті https://site.com, воно не буде доступне на тому ж сайті з протоколом HTTP, як http://site.com. Таким чином, якщо в cookie зберігається конфіденційна інформація, яку не слід передавати за незашифрованим протоколом HTTP, потрібно встановити цей прапор.

// передбачається, що зараз ми на https:// // встановимо опцію secure для cookie (cookie доступно тільки через HTTPS) document.cookie = "user=John; secure";

samesite

Це ще одне налаштування безпеки, що застосовується для захисту від так званої XSRF-атаки (міжсайтова підробка запиту).

Щоб зрозуміти, як налаштування працює і де може бути корисним, подивимося на XSRF-атаки.

Атака XSRF

Уявіть, що ви авторизувалися на сайті bank.com. Тобто: у вас є кукі для аутентифікації з цього сайту. Ваш браузер надсилає його на сайт bank.com з кожним запитом, щоб сервер цього сайту дізнавався про вас і виконував усі конфіденційні фінансові операції.

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

Браузер посилає куки при кожному відвідуванні bank.com, навіть якщо форму було відправлено з evil.com. Таким чином, банк дізнається про вас і виконає платіж.

Така атака називається міжсайтова підробка запиту (або Cross-Site Request Forgery, XSRF).

Звісно ж, у реальному житті банки захищені від такої атаки. У всіх формах, що згенерували сайт. назад).І сайт bank.com, при отриманні форми, перевіряє його наявність.

Але такий захист вимагає зусиль на її реалізацію: нам потрібно переконатися, що у кожній формі є поле з токеном, також ми маємо перевірити всі запити.

Налаштування samesite

Параметр cookie samesite надає ще один спосіб захисту від таких атак, який (теоретично) не повинен вимагати «токени захисту xsrf».

У нього є два можливі значення:

Куки з samesite=strict ніколи не відправляться, якщо користувач прийшов не з цього сайту.

Іншими словами, якщо користувач переходить по посиланню з пошти, відправляє форму з evil.com або виконує будь-яку іншу операцію, що відбувається з іншого домену, то кукі не відправляється.

Якщо cookie мають налаштування samesite, то атака XSRF не має шансів на успіх, тому що відправка з сайту evil.com відбувається без cookie. Таким чином, сайт bank.com не розпізнає користувача та не здійснить платіж.

Захист досить надійний. Куки з налаштуванням samesite буде відправлено тільки в тому випадку, якщо операції відбуваються з сайту bank.com, наприклад, відправлення форми зроблено зі сторінки на bank.com.

Хоча є невеликі незручності.

Коли користувач перейде за посиланням на bank.com, наприклад, зі своїх нотаток, він буде здивований, що сайт bank.com не впізнав його. Справді, cookie з samesite=strict у цьому випадку не відправляється.

Ми могли б обійти це обмеження, використовуючи два куки: одне куки для «загального впізнавання», лише для того, щоб привітатися: «Привіт, Джоне», та інше куки для операцій зміни даних з samesite=strict . Тоді користувач, який прийшов на сайт, побачить вітання, але платежі потрібно ініціювати з сайту банку, щоб вирушило друге куки.

Це м'якіший варіант, який також захищає від XSRF і при цьому не псує враження від використання сайту.

Режим Lax так само, як і strict, забороняє браузеру відправляти куки, коли запит відбувається не з сайту, але додає один виняток.

Куки з samesite=lax відправляється, якщо дві ці умови вірні:

  1. Використовуються безпечні методи HTTP (наприклад, GET, але не POST). Повний список безпечних HTTP-методів можна переглянути у специфікації RFC7231. По суті, безпечними є методи, які зазвичай використовуються для читання, але не для запису даних. Вони не повинні виконувати жодних операцій на зміну даних. Перехід за посиланням завжди є GET-методом, тобто безпечним.
  2. Операція здійснює навігацію верхнього рівня (змінює URL-адресу в адресному рядку браузера). Зазвичай це так, але якщо навігація виконується в , це не верхній рівень. Крім того, JavaScript-методи для мережевих запитів не виконують жодної навігації, тому вони не підходять.

Таким чином, режим samesite=lax дозволяє найпоширенішій операції «перехід за посиланням» передавати куки. Наприклад, відкриття сайту із нотаток задовольняє цим умовам.

Але щось складніше, наприклад, мережевий запит з іншого сайту або надсилання форми, втрачає куки.

Якщо це вам підходить, то додавання samesite=lax швидше за все не зіпсує враження користувачів від роботи з сайтом і додасть захисту.

В цілому, тежвідмінна настройка.

Але вона має важливий недолік:

  • samesite ігнорується (не підтримується) старими браузерами, випущеними до 2017 року та раніше.

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

Але ми, безумовно, можемо використовувати samesite разом з іншими методами захисту, такими як XSRF-токени, щоб додати додатковий шар захисту, а потім, у майбутньому, коли старі браузери повністю зникнуть, ми, ймовірно, зможемо повністю видалити XSRF-токени.

httpOnly

Ця установка не має нічого спільного з JavaScript, але ми повинні згадати її для повноти викладу.

Веб-сервер використовує заголовок Set-Cookie для встановлення cookie. І він може встановити налаштування http Only.

Це налаштування забороняє будь-який доступ до cookie з JavaScript. Ми не можемо бачити таке куки або маніпулювати ним за допомогою document.cookie.

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

Зазвичай, якщо таке відбувається, і користувач заходить на сторінку з JavaScript-кодом хакера, то цей код виконується та отримує доступ до document.cookie, і тим самим до куки користувача, які містять автентифікаційну інформацію. Це погано.

Але якщо cookie має налаштування httpOnly , то document.cookie не бачить його, тому таке cookie захищене.

Додаток: Функції для роботи з куки

Ось невеликий набір функцій для роботи з cookie, зручніших, ніж ручна модифікація document.cookie.

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

getCookie(name)

Найкоротший спосіб отримати доступ до cookie – це використовувати регулярні вирази.

Функція getCookie(name) повертає cookie із зазначеним name :

// повертає cookie із зазначеним name, // або undefined, якщо нічого не знайдено function getCookie(name) < let matches = document.cookie.match(new RegExp( "(?:^|; )" + name.replace(/ ([\.$?*|<>\(\)\[\]\/\+^])/g, '\$1') + "=([^;]*)" ));return matches? decodeURIComponent(matches[1]) : undefined; >

Тут new RegExp генерується динамічно, щоб знаходити ; name=.

Зверніть увагу, значення cookie кодується, тому getCookie використовує вбудовану функцію decodeURIComponent для декодування.

setCookie(name, value, options)

Встановлює cookie з іменем name і значенням value , з налаштуванням path=/ за умовчанням (можна змінити, щоб додати інші значення за замовчуванням):

function setCookie(name, value, options = <>) < options = < path: '/', // за необхідності додайте інші значення за промовчанням . options >; if (options.expires instanceof Date) < options.expires = options.expires.toUTCString(); >let updatedCookie = encodeURIComponent(name) + "=" + encodeURIComponent(value); for (let optionKey in options) < updatedCookie += ";" + optionKey; let optionValue = options[optionKey]; if (optionValue !== true) < updatedCookie += "=" + optionValue; >> document.cookie = updatedCookie; > // Приклад використання: setCookie('user', 'John', );

deleteCookie(name)

Щоб видалити куки, ми можемо встановити негативну дату закінчення терміну дії:

function deleteCookie(name) < setCookie(name, "", < 'max-age': -1 >) >

Зверніть увагу: коли ми оновлюємо або видаляємо куки, нам слід використовувати тільки такі ж налаштування шляху та домену, як при встановленні куки.

Додаток: Сторонні куки

Куки називаються сторонніми, якщо вони розміщені з домену, який відрізняється від сторінки, яку відвідує користувач.

  1. Сторінка site.com завантажує банер з іншого сайту: .
  2. Разом з банером віддалений сервер ads.com може встановити заголовок Set-Cookie з куки, наприклад, id=1234. Такі куки створюються з домену ads.com і буде видно тільки на сайті ads.com :

Сторонні куки в силу своєї специфіки зазвичай використовуються з метою відстеження відвідуваних сторінок і показу реклами. Вони прив'язані до вихідного домену, тому ads.com може відслідковувати одного і того ж користувача на різних сайтах, якщо звідти йдеться до нього.

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

Крім того, деякі сучасні браузери використовують спеціальні політики для таких кукі:

  • Safari взагалі не дозволяє сторонні куки.
  • Firefox має "чорний список" сторонніх доменів, чиї сторонні куки він блокує.

Якщо ми завантажуємо скрипт із стороннього домену, наприклад , і цей скрипт використовує document.cookie для встановлення cookie, то таке cookie не є стороннім.

Якщо скрипт встановлює куки, то немає різниці, звідки був завантажений скрипт – куки належить домену поточної веб-сторінки.

Додаток: GDPR

Ця тема взагалі не пов'язана з JavaScript, але слід її мати на увазі при встановленні cookie.

У Європі існує законодавство під назвою GDPR, яке встановлює для сайтів низку правил, що забезпечують конфіденційність користувачів. І одним з таких правил є вимога явного дозволу від користувача на використання куки, що відстежують.

Зверніть увагу, це стосується тільки cookie, які використовуються для відстеження/ідентифікації/авторизації.

Тобто, якщо ми встановимо куки, які просто зберігають деяку інформацію, але не відстежують і не ідентифікують користувача, ми вільні від цього правила.

Але якщо ми збираємося встановити куки з інформацією про аутентифікацію або з ідентифікатором відстеження, то користувач має явно це дозволити.

Є два основні варіанти, як сайти слідують GDPR. Ви напевно вже бачили їх у мережі:

  1. Якщо сайт хоче встановити кукі для відстеження лише для авторизованих користувачів. То в реєстраційній формі має бути встановлений прапорець «прийняти політику конфіденційності» (яка визначає, як використовуються куки), користувач повинен встановити його, і лише тоді сайт зможе використовувати авторизаційні куки.
  2. Якщо сайт хоче встановити cookie для відстеження всім користувачам. Щоб зробити це законно, сайт показує модальне вікно для користувачів, які зайшли вперше, і вимагає від них згоди використання cookie. Потім сайт може встановити такі cookie і показати користувачеві вміст сторінки. Хоча це створює незручності для нових відвідувачів – нікому не подобається спостерігати за модальними вікнами замість контенту. Але GDPR у цій ситуації вимагає явної згоди користувача.

GDPR стосується не тільки куки, але й інших питань, пов'язаних із конфіденційністю, які виходять за рамки матеріалу цього розділу.

Разом

document.cookie надає доступ до cookie.

  • Операція запису змінює лише те куки, яке було вказано.
  • Ім'я та значення cookie мають бути закодовані.
  • Одне cookie вміщує до 4kb даних, дозволяється більше 20 cookie на сайт (залежить від браузера).
  • path=/ , за замовчуванням встановлюється поточний шлях, робить куки видимим лише зазначеним шляхом і нижче.
  • domain=site.com , за умовчанням куки видно лише на поточному домені, якщо явно вказаний домен, то куки видно і піддоменах.
  • expires або max-age встановлює дату закінчення терміну дії, без них кукі помре під час закриття браузера.
  • secure робить cookie доступним лише при використанні HTTPS.
  • samesite забороняє браузеру відправляти куки із запитами, що надходять ззовні, допомагає запобігти XSRF-атакам.
  • Сторонні куки можуть бути заборонені браузером, наприклад, Safari робить це за замовчуванням.
  • Встановлення відстежуваних куки користувачам з країн ЄС вимагає їхньої явної згоди на це відповідно до законодавства GDPR.

Ультимативний гайд HTTP. Cookies та CORS

Привіт! Мене звуть Івасюта Олексій, я Техлід команди Bricks в Авіто в кластері Architecture, а це мій цикл статей про протокол HTTP. У першій частині ми вже познайомилися з версією протоколу 1.0 та поговорили про структуру відповідей та запитів. Тепер настав час дізнатися, що таке Cookies і для чого потрібний CORS.

Cookies

HTTP – це протокол без збереження стану. Це означає, що коли на сервер надходять два запити, він не розуміє: їх надіслав один клієнт або різні. У реальних додатках постійно треба ідентифікувати користувача: перевіряти, чи авторизований він, виводити рекомендації користувача, зберігати кошик обраних товарів у магазині. Для цього є механізм Cookies.

Cookies — це фрагмент даних, у яких сервер передає важливу інформацію клієнта. Браузер отримує цей фрагмент, зберігає його та з кожним наступним запитом відсилає назад на сервер. Так він розуміє, від якого клієнта надійшов запит.

Куки виглядають як пара ключ = значення . Для встановлення сервер повинен у відповіді на запит клієнта надіслати заголовок Set-Cookie зі значенням.

Set-Cookie: token=123abc

Як тільки браузер отримає його у відповідь на запит, він збереже значення cookie у Cookie Storage. У кожний наступний запит браузер додаватиме збережені значення в заголовку Cookie.

Приклад вище - це сесійний куки, їм не вказуються терміни зберігання.Він буде існувати, доки користувач не закриє вкладку із сайтом у браузері. Але багато браузерів використовують механізм відновлення сесій, тому сесійні куки теоретично можуть жити вічно.

Зазвичай кукам встановлюється фіксований час життя. Це можна зробити двома способами:

  • встановити дату закінчення терміну придатності - Expires ,
  • встановити кількість секунд, після яких кука перестане бути актуальною - MAX_AGE.

Припустимо, термін життя кукі з попереднього прикладу має скінчитися 1 січня 2030 року. Тоді потрібно надіслати заголовок зі значенням куки та датою закінчення терміну придатності, розділеними крапкою з комою.

Set-Cookie: token = 123abc; Expires=Tue, 01 Jan 2030 00:00:00 -0000

Тепер із настанням 1 січня 2030 року кука стане невалідною та вилучиться.

В альтернативному варіанті термін життя кукі повинен спливти за дві хвилини. Тоді замість дати потрібно надіслати кількість секунд у параметрі MAX_AGE:

Set-Cookie: token = 123abc; MAX_AGE=120

Різні браузери можуть використовувати різні параметри для встановлення часу життя cookie. Тому найчастіше сервер надсилає обидва варіанти, а браузер сам вибирає параметр, що підтримується.

Set-Cookie: token = 123abc; Expires = Thu, 05 Aug 2021 18:45:00 -0000; MAX_AGE=120

Стандарт RFC6265 1 описує куки. Він закріплює правило, що імена параметрів – реєстронезалежні. Тому цей запис теж буде валідним:

Set-Cookie: token = 123abc; expires=Thu, 05 Aug 2021 18:45:00 -0000; max_age=120

Область видимості Cookies

Параметри domain і path керують областю видимості cookie і визначають, на яких піддоменах та для яких URL вони працюватимуть. Якщо не вказати параметр domain , то він за умовчанням дорівнюватиме хосту сайту, наприклад, example.com.Тоді куки не працюватимуть для піддоменів, наприклад test.example.com . Якщо вказати значення domain , то cookie буде працювати для хоста і всіх піддоменів.

Параметр path вказує, за якими URL при запиті ресурсів необхідно передавати куку в заголовку. Якщо встановити path=/ , куки будуть надсилатися для всіх запитів. Якщо вказати значення path=/api , вони будуть передаватися всім запитів на ресурси, URL яких починається з /api .

Розширимо попередній приклад:

Set-Cookie: token = 123abc; expires=Thu, 05 Aug 2021 18:45:00 -0000; max_age = 120; domain=example.com; path=/api

Унікальний ідентифікатор cookie - їх ключ (у прикладі - token), значення domain і path. Якщо потрібно перевизначити значення раніше встановлених куки, ці три параметри повинні збігатися. В іншому випадку браузер створить нові. А ще не існує методу видалення куки. Можна тільки встановити її повторно і вказати дату закінчення терміну придатності expires у минулому або нульовий або негативний max_age.

Захист Cookies

Cookies представляють два параметри, які захищають їх від різних атак.

Параметр secure говорить про те, що такі cookie будуть надсилатися тільки по HTTPS-з'єднанню. Якщо сайт працює через HTTP, значення не буде передано. Secure не забезпечує додаткового шифрування, тому не варто зберігати чутливі дані в куках.

httpOnly створює куки, до яких не можна звернутися з коду JavaScript у браузері. Так можна уникнути XSS-атак. 2

Надсилання на сервер

Куки відправляються на сервер при кожному запиті, якщо не підійшла дата закінчення терміну придатності та параметри path і domain відповідає URL ресурсу. Вони передаються одним рядком у значенні заголовка запиту cookie і поділяються крапкою з комою.

Cookie: key1 = value1; key2=value2;

Директива Євросоюзу про Cookie

25 травня 2011 року набула чинності Директива 2009/136/EC Євросоюзу про кукі.3 Вона вимагає запиту дозволу користувача на отримання та використання інформації з його комп'ютера. Тому майже кожен сайт при першому відвідуванні або після очищення кешу виводить банер із запитом на використання Cookies.

CORS

За промовчанням у браузері діє політика безпеки Same Origin Policy. Це означає, що доступ до ресурсів можна отримати, лише якщо джерело цих ресурсів та джерело запиту збігаються. Це зроблено для того, щоб сайт хакерів evil.com не міг отримати доступ, наприклад, до поштової скриньки на домені gmail.com і прочитати листи. Ця стратегія працювала довгий час, коли JavaScript вважався браузерною мовою для прикрашання сторінок і не вмів робити AJAX-запити.

Згодом розробники зрозуміли, що хочуть вміти надсилати дані на сервер та отримувати їх за допомогою асинхронних запитів. Але політика Same Origin не дозволяє це зробити. Після довгих обговорень було запропоновано механізм CORS – Cross-Origin Resource Sharing.

Цей механізм використовує додаткові заголовки HTTP. З ним браузер користувача отримує дозволи на доступ до вибраних ресурсів, якщо домен сайту та домен запитуваного ресурсу відрізняються.

Наприклад, сайт знаходиться на домені example.com. Запит надсилається на сайт, який знаходиться на домені web-server.com. Спочатку браузер повинен зрозуміти, складний цей запит або простий. Простий запит надсилається методом GET, POST або HEAD і містить лише наступні заголовки:

  • Accept;
  • Accept-Language;
  • Content-Language;
  • Content-Type зі значенням application/x-www-form-urlencoded , multipart/form-data або text/plain .

Інші запити вважаються складними. Наприклад, якщо він відправляється методом DELETE або містить назву Authorization . Прості запити браузер відправляє безпосередньо на сервер і автоматично додає до них заголовок Origin. Його значення дорівнює URL хоста, з якого надсилається запит.У нашому прикладі це Origin: https://example.com.

POST /path HTTP/1.0 Host: web-server.com Origin: example.com Content-Type: text/plain

Сервер приймає такий запит і визначає, чи дозволити хосту отримати цей ресурс або відмовити в запиті. Для цього у відповіді використовується спеціальний заголовок Access-Control-Allow-Origin. Він визначає, із яких джерел дозволено приймати запити. Якщо вказати Access-Control-Allow-Origin: http://example.com , запит на ресурс буде завжди дозволений лише домену example.com . Якщо потрібно дозволити отримувати ресурс із будь-якого домену, то у відповіді на запит має бути заголовок Access-Control-Allow-Origin: * .

Браузер заблокує відповідь на запит, якщо:

  • сервер поверне у відповіді заголовок Access-Control-Allow-Origin: null ,
  • значення не збігатиметься з переданим у заголовку запиту Origin ,
  • не буде заголовка.

Якщо браузер виявить складний запит, то спочатку відправить серверу preflight — попередній запит за допомогою HTTP-методу OPTIONS . У запит додається заголовок Access-Control-Request-Method , у значенні якого вказується HTTP-метод оригінального запиту.

Якщо в оригінальному запиті передаються заголовки не зі списку дозволених, то запит OPTIONS додатково додається заголовок Access-Control-Request-Headers . У його значенні через кому перераховуються всі заголовки оригінального запиту.

У разі надсилання preflight-запиту сервер також повинен повернути заголовок Access-Control-Allow-Origin з необхідним значенням.

Якщо в запит додано заголовок Access-Control-Request-Method , то сервер у відповіді повинен вказати, які HTTP-методи дозволено використовувати для запиту ресурсу в заголовку відповіді Access-Control-Allow-Methods .

Якщо до запиту додано заголовок Access-Control-Request-Headers, то сервер у відповіді повинен вказати, які HTTP-заголовки дозволено використовувати для запиту ресурсу в заголовку відповіді Access-Control-Allow-Headers.

Приклад відповіді на preflight-запит:

HTTP/1.0 200 OK Дата: Thu, 29 Jul 2021 19:20:01 GMT Connection: close Server: gunicorn/19.9.0 Access-Control-Allow-Origin: * Access-Control-Allow-Methods: DELETE, GET, POST Access-Control-Allow-Headers: X-Custom-Header, Authorization

Браузер отримує відповідь і після цього звіряє значення Origin, дозволених заголовків та методів. Якщо все збігається, надсилає оригінальний запит на сервер. Якщо дозволені параметри не збігаються з фактичними, браузер блокує надсилання оригінального запиту та повідомляє про помилку.

Іноді потрібно вміти надсилати Cookies при зверненні до інших доменів. Заголовок Cookie не відноситься до списку дозволених і підпадає під політику безпеки. Щоб їх можна було передавати, сервер у відповідь на preflight і оригінальний запит повинен повертати заголовок Access-Control-Allow-Credentials: true . Для роботи cookie також потрібно повертати в заголовку Access-Control-Allow-Origin конкретне значення дозволеного хоста.

Відповідь від кросдоменного запиту отримано. Допустимо, потрібно отримати доступ до заголовків у коді JavaScript у браузері та прочитати їх значення. Зробити це не так просто, тому що за замовчуванням доступ із Java Script для кросдоменних запитів є лише до таких заголовків:

  • Cache-Control
  • Content-Language
  • Content-Length
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

Якщо JS спробує прочитати значення іншого заголовка, отримає null. Але сервер у відповіді на запит може перерахувати заголовки, до яких можна отримати доступ із Javascript у заголовку Access-Control-Expose-Headers. Заголовки вказуються через кому. Наприклад, Access-Control-Expose-Headers: Authorization, X-Version .

Заголовок відповіді сервера Access-Control-Max-Age повідомляє браузеру, наскільки попереднє запит може бути кешований і опущений при запитах до сервера. Значення вказується за секунди. Якщо після першого виконання preflight-запиту час життя Max-Age не вийшов, повторного відправлення не буде. Оригінальний запит виконається одразу.

Про Cookies і CORS на цьому все. У третій статті циклу я розповім про нововведення у версії HTTP/1.1 і чим вона відрізняється від HTTP/2.

Корисні посилання

Схожі статті

  • Як передаються віруси у котів
  • Які основні види запитів у SQL ви знаєте
  • Які шкірні хвороби передаються від собак
  • Які хвороби передаються від курки до людини
  • Хто перемагає у запиті котирувань
  • Недавні статті

  • Як бродить зернова брага
  • Що робити якщо не засмагаєш на сонці чому засмага погано лягає на шкіру або перестає прилипати
  • Як швидко зняти гель лак без апарату
  • Як робиться Каті голови
  • Яка гребінець краще для об'єму
  • Чим роблять м'яку покрівлю
  • Чи можна залишати крем для обличчя на ніч
  • Де знаходиться датчик селектора
  • географія нашої діяльності
    вулиця Драгоманова, 27
    вул. Курчатова 1Б
    вул. Міцкевича 130
    вул. Лабунського, 1
    вул. Макарова-Пржевальського
    вул. Толстого 10
    вул. Грушевського 28
    вул. Перший промінь (Черняхівського)
    напишіть нам

    сообщение успешно отправлено
    x