tl; dr - у кінці підсумків та заголовки у відповіді, щоб полегшити пошук відповідних частин. Читати все рекомендується, хоча це дає корисну основу для розуміння того, чому це полегшує бачення того, як застосовується в різних обставинах.
Про ту саму політику щодо походження
Це та сама політика щодо походження . Це функція безпеки, реалізована браузерами.
Ваш конкретний випадок показує, як він реалізований для XMLHttpRequest (і ви отримаєте однакові результати, якщо використовували б видобуток), але це стосується і інших речей (наприклад, зображень, завантажених у <canvas>
або документи, завантажених у <iframe>
), лише за допомогою трохи інші реалізації.
(Дивно, що це стосується також шрифтів CSS, але це тому, що знайдені ливарні наполягають на DRM, а не на питаннях безпеки, які зазвичай стосується та ж політика оригіналу).
Стандартний сценарій, що демонструє потребу в SOP, може бути продемонстрований трьома символами :
- Аліса - людина з веб-браузером
- Боб запускає веб-сайт (
https://www.[website].com/
у вашому прикладі)
- Mallory запускає веб-сайт (
http://localhost:4300
у вашому прикладі)
Аліса увійшла на сайт Боба і має там деякі конфіденційні дані. Можливо, це інтранет компанії (доступний лише браузерам в локальній мережі), або її інтернет-банкінг (доступний лише за допомогою файлу cookie, який ви отримуєте після введення імені користувача та пароля).
Аліса відвідує веб-сайт Mallory, який має деякий JavaScript, який змушує браузер Аліси запитувати HTTP-запит на веб-сайт Боба (з її IP-адреси з її cookie тощо). Це може бути таким же простим, як використання XMLHttpRequest
та читання програми responseText
.
Політика щодо самого оригіналу браузера перешкоджає тому, щоб JavaScript читав дані, повернені веб-сайтом Боба (до яких Боб і Аліса не хочуть, щоб Маллорі отримував доступ). (Зверніть увагу, що ви можете, наприклад, відображати зображення за допомогою <img>
елемента з різними джерелами, оскільки вміст зображення не піддається JavaScript (або Mallory)…, якщо ви не кинете полотно в суміш, і в цьому випадку ви будете генерувати те саме походження помилка порушення).
Чому та сама політика щодо походження застосовується, якщо ви не вважаєте, що вона повинна
Для будь-якої заданої URL-адреси можливо, що SOP не потрібен. Кілька поширених сценаріїв, коли це так:
- Аліса, Боб і Меллорі - одна і та ж людина.
- Боб надає повністю публічну інформацію
… Але браузер не має можливості знати, чи є одне з перерахованих вище правдивим, тому довіра не є автоматичною і застосовується SOP. Дозвіл повинен бути наданий явно до того, як браузер надасть дані, отримані на іншому веб-сайті.
Чому така ж політика щодо оригіналу застосовується лише до JavaScript на веб-сторінці
Розширення браузера *
, вкладка "Мережа" в інструментах для розробників браузера та додатках, таких як Postman, встановлено програмне забезпечення. Вони не передають дані з одного веб-сайту на JavaScript, що належить іншому веб-сайту лише тому, що ви відвідали цей інший веб-сайт . Встановлення програмного забезпечення зазвичай займає більш свідомий вибір.
Не існує третьої сторони (Маллорі), яка вважається ризиком.
*
Розширення для веб-переглядачів потрібно ретельно писати, щоб уникнути проблем із перехресним походженням. Наприклад, перегляньте документацію Chrome .
Чому ви можете відображати дані на сторінці, не читаючи їх за допомогою JS
Існує ряд обставин, коли сайт Mallory може змусити браузер отримувати дані від третьої сторони та відображати їх (наприклад, додаючи <img>
елемент для відображення зображення). Однак JavaScript Mallory не може зчитувати дані цього ресурсу, але це може робити лише браузер Аліси та сервер Боба, тому це все ще захищено.
CORS
Access-Control-Allow-Origin
HTTP відповідь заголовок , передбачений в повідомленні про помилку є частиною CORS стандарту , що дозволяє Бобу явним чином надати дозвіл на сайт Меллорі , щоб отримати доступ до даних через браузер Аліси.
Основна реалізація буде просто включати:
Access-Control-Allow-Origin: *
… У заголовках відповідей дозволити будь-якому веб-сайту читати дані.
Access-Control-Allow-Origin: http://example.com/
… Дозволив би отримати доступ до нього лише певному сайту, і Боб може динамічно генерувати його на основі заголовка Origin
запиту, щоб дозволити декілька, але не всі сайти отримати доступ до нього.
Особливості того, як Боб встановлює цей заголовок відповіді, залежать від HTTP-сервера та / або мови програмування на стороні сервера. Існує колекція посібників для різних поширених конфігурацій, які можуть допомогти.
Примітка: Деякі запити є складними і надсилають запит OPTIONS перед передпольотом , на який повинен відповісти сервер, перш ніж браузер надішле GET / POST / PUT / Незалежно від запиту, який хоче зробити JS. Реалізація CORS, яка додає лише Access-Control-Allow-Origin
до певних URL-адрес, цим часто користується.
Очевидно, що надання дозволу через CORS - це те, що Боб зробив би лише у тому випадку, якщо:
- Дані не були приватними або
- Маллорі довіряли
Але я не Боб!
Не існує стандартного механізму для додавання цього заголовка Меллорі, оскільки він має надходити з веб-сайту Боба, який вона не контролює.
Якщо у Боб працює загальнодоступний API, можливо, існує механізм увімкнення CORS (можливо, шляхом форматування запиту певним чином, або параметр конфігурації після входу на веб-сайт порталу розробників для сайту Боба). Це, мабуть, буде механізмом, реалізованим Боб. Меллорі могла прочитати документацію на сайті Боба, щоб побачити, чи щось є, або вона могла б поговорити з Боб і попросити його запровадити CORS.
Повідомлення про помилки, в яких згадується "Відповідь за передполіт"
Деякі запити перехресного походження попередньо висвітлюються .
Це відбувається, коли (грубо кажучи) ви намагаєтеся зробити запит перехресного походження, який:
- Включає облікові дані, як куки
- Неможливо створити звичайну форму HTML (наприклад, має власні заголовки або тип вмісту, який ви не можете використовувати у формах
enctype
).
Якщо ви правильно робите щось, що потребує попереднього польоту
У цих випадках тоді решта цієї відповіді все-таки застосовується, але вам також потрібно переконатися, що сервер може прослухати запит перед польотом (який буде OPTIONS
(а не GET
, POST
або все, що ви намагалися надіслати), і відповісти на нього правом Access-Control-Allow-Origin
заголовок , але також Access-Control-Allow-Methods
і Access-Control-Allow-Headers
щоб ваші конкретні методи HTTP або заголовки.
Якщо ви запускаєте передпольотний помилку
Іноді люди роблять помилки, намагаючись побудувати запити Ajax, а іноді вони викликають потребу в передпольоті. Якщо API розроблений так, щоб дозволяти запити перехресного походження, але не вимагає нічого, що потребує попереднього польоту, то це може порушити доступ.
Поширені помилки, які викликають це, включають:
- намагаються поставити
Access-Control-Allow-Origin
та інші заголовки відповідей CORS на запит. Вони не належать до запиту, не робіть нічого корисного (який би був сенс системи дозволів, де ви могли б надати собі дозвіл?), І повинні з’являтися лише у відповіді.
- намагаючись поставити
Content-Type: application/json
заголовок на запит GET, який не має органу запиту для опису вмісту (зазвичай, коли автор плутає Content-Type
та Accept
).
У будь-якому з цих випадків видалення додаткового заголовка запиту часто буде достатньо, щоб уникнути необхідності попереднього перельоту (що вирішить проблему під час спілкування з API, що підтримують прості запити, але не попередньо розібрані запити).
Непрозорі відповіді
Іноді потрібно зробити запит HTTP, але не потрібно читати відповідь. наприклад, якщо ви розміщуєте повідомлення журналу на сервері для запису.
Якщо ви використовуєте в fetch
API (замість XMLHttpRequest
), то ви можете налаштувати його , щоб не намагатися використовувати CORS.
Зауважте, що це не дозволить вам зробити все, що вимагає CORS. Ви не зможете прочитати відповідь. Ви не зможете зробити запит, який вимагає попереднього перельоту.
Це дозволить вам зробити простий запит, не побачити відповідь і не заповнити Консоль розробника повідомленнями про помилки.
Як це зробити, пояснюється повідомленням про помилку Chrome, яке надається, коли ви робите запит, використовуючи fetch
та не отримуючи дозволу на перегляд відповіді за допомогою CORS:
Доступ до вибору у " https://example.com/
" від походження " https://example.net
'був заблокований політикою CORS: Access-Control-Allow-Origin
на запитуваному ресурсі немає заголовка " ". Якщо непрозора відповідь відповідає вашим потребам, встановіть режим запиту на "no-cors", щоб отримати ресурс з вимкненим CORS.
Таким чином:
fetch("http://example.com", { mode: "no-cors" });
Альтернативи CORS
JSONP
Боб також міг би надати дані, використовуючи хак, як JSONP , так люди перехрещували Ajax до того, як з'явився CORS.
Це працює, представляючи дані у вигляді програми JavaScript, яка вводить дані на сторінку Маллорі.
Це вимагає, щоб Маллорі довіряв Бобу не надавати шкідливий код.
Зверніть увагу на загальну тему: Сайт, що надає дані, повинен повідомити веб-переглядачу, що для веб-сайту третьої сторони це нормально для доступу до даних, які він надсилає до браузера.
Оскільки JSONP працює, додаючи <script>
елемент для завантаження даних у вигляді програми JavaScript, яка викликає функцію вже на сторінці, спроба використовувати техніку JSONP за URL-адресою, яка повертає JSON, не вдасться - як правило, з помилкою CORB - тому що JSON не JavaScript.
Перемістіть два ресурси до одного Походження
Якщо HTML-документ, у якому працює JS, і запитувана URL-адреса мають одне і те ж походження (спільне використання тієї самої схеми, імені хоста та порту), тоді вони за тією ж політикою оригіналу надають дозвіл за замовчуванням. CORS не потрібен.
Проксі
Маллорі може використовувати код на стороні сервера для отримання даних (які вона може передати зі свого сервера до браузера Аліси через HTTP як зазвичай).
Буде або:
- додайте заголовки CORS
- конвертувати відповідь у JSONP
- існують з тим самим походженням, що і документ HTML
Цей код на стороні сервера може бути записаний та розміщений третьою стороною (наприклад, CORS Anywhere). Зауважте, що це стосується конфіденційності. Третя сторона може відстежувати, хто надає проксі на своїх серверах.
Боб не повинен давати жодних дозволів, щоб це сталося.
Тут немає ніяких наслідків для безпеки, оскільки це саме між Меллорі та Боб. Боб не може подумати, що Меллорі - це Аліса, і надати Маллорі дані, які слід зберігати в таємниці між Алісою та Боб.
Отже, Маллорі може використовувати цей прийом лише для читання публічних даних.
Однак зауважте, що забирати вміст з чужого веб-сайту та показувати його самостійно може бути порушенням авторських прав і відкрити для вас правових дій.
Написання чогось іншого, ніж веб-додаток
Як зазначалося в розділі "Чому однакова політика щодо оригіналу застосовується лише до JavaScript на веб-сторінці", ви можете уникнути SOP, не записуючи JavaScript на веб-сторінці.
Це не означає, що ви не можете продовжувати використовувати JavaScript та HTML, але ви можете поширити його за допомогою іншого механізму, наприклад Node-WebKit або PhoneGap.
Розширення браузера
Розширення браузера може вводити заголовки CORS у відповідь до того, як буде застосовано таку саму політику походження.
Вони можуть бути корисними для розробки, але не є практичними для виробничого сайту (просити кожного користувача вашого сайту встановити розширення браузера, яке відключає функцію безпеки свого браузера, нерозумно).
Вони також прагнуть працювати лише з простими запитами (у разі відмови під час обробки передпольотних запитів OPTIONS).
Забезпечення належного середовища розробки з локальним сервером розвитку
зазвичай є кращим підходом.
Інші ризики безпеки
Зауважте, що SOP / CORS не пом'якшує атаки XSS , CSRF або SQL Injection, з якими потрібно обробляти незалежно.
Підсумок
- У вашому клієнтському коді нічого не можна зробити, що дозволить CORS отримати доступ до чужого сервера.
- Якщо ви керуєте сервером, запит робиться: Додайте до нього дозволи CORS.
- Якщо ви дружите з людиною, яка ним керує: Запропонуйте їм додати до нього дозволи CORS.
- Якщо це державна послуга:
- Прочитайте їх документацію API, щоб побачити, що вони говорять про доступ до неї за допомогою клієнтського JavaScript:
- Вони можуть сказати вам використовувати конкретні URL-адреси
- Вони можуть підтримувати JSONP
- Вони можуть взагалі не підтримувати перехресний доступ із коду клієнта (це може бути навмисним рішенням з міркувань безпеки, особливо якщо вам потрібно передати персоналізований ключ API у кожному запиті).
- Переконайтеся, що ви не запускаєте запит перед передпольотом, який вам не потрібен. API може надати дозвіл на прості запити, але не заздалегідь розібрані запити.
- Якщо нічого з перерахованого вище не застосовується: Запропонуйте браузеру поговорити зі своїм сервером, а потім дозвольте вашому серверу отримати дані з іншого сервера та передати його. (Є також сторонні сервісні послуги, які прикріплюють заголовки CORS до загальнодоступних ресурсів, якими ви можете користуватися).