javascript — XMLHttpRequest не может загрузить XXX Нет заголовка «Access-Control-Allow-Origin»

ТЛ; др; О той же политике происхождения

У меня есть процесс Grunt, который инициирует экземпляр сервера express.js. Это работало абсолютно нормально до тех пор, пока не началось обслуживание пустой страницы со следующим появлением в журнале ошибок в консоли разработчика в Chrome (последняя версия):

XMLHttpRequest не может загрузить https://www.example.com/
Нет заголовка «Access-Control-Allow-Origin» в запрошенном
ресурс. ПроисхождениеHTTP: // локальный: 4300Поэтому не допускается доступ.

Что мешает мне получить доступ к странице?

63

Решение

Это Политика единого происхождения. Это функция безопасности, реализованная в браузерах.

Ваш конкретный случай показывает, как он реализован для XMLHttpRequest (и вы получите идентичные результаты, если будете использовать fetch), но это также относится и к другим вещам (например, к изображениям, загруженным в <canvas> или документы, загруженные в <iframe>), только с немного другими реализациями.

(Как ни странно, это также относится к CSS-шрифтам, но это потому, что найденные литейщики настаивали на DRM, а не на проблемах безопасности, которые обычно покрывает та же политика происхождения).

Стандартный сценарий, который демонстрирует необходимость СОП, может быть продемонстрирован с три персонажа:

  • Алиса — человек с веб-браузером
  • Боб заведует сайтом (https://www.[website].com/ в твоем примере)
  • Мэллори управляет сайтом (http://localhost:4300 в твоем примере)

Алиса вошла на сайт Боба и там хранит некоторые конфиденциальные данные. Возможно, это интранет компании (доступный только для браузеров в локальной сети) или ее онлайн-банкинг (доступ только с помощью cookie-файла, который вы получаете после ввода имени пользователя и пароля).

Алиса посещает веб-сайт Мэллори, на котором есть некоторый JavaScript, который заставляет браузер Алисы отправлять HTTP-запрос на веб-сайт Боба (с ее IP-адреса с помощью файлов cookie и т. Д.). Это может быть так же просто, как с помощью XMLHttpRequest и читать responseText,

Политика одинакового происхождения браузера запрещает JavaScript читать данные, возвращаемые веб-сайтом Боба (к которым Боб и Алиса не хотят, чтобы Мэллори получала доступ). (Обратите внимание, что вы можете, например, отобразить изображение, используя <img> элемент через источник, потому что содержимое изображения не подвергается JavaScript (или Мэллори) … если вы не добавите холст в смесь, в этом случае вы будут генерировать ошибку нарушения того же происхождения).


Для любого данного URL возможно, что СОП не нужен. Несколько распространенных сценариев, где это имеет место:

  • Алиса, Боб и Мэллори — один и тот же человек.
  • Боб предоставляет полностью публичную информацию

… но браузер не может узнать, верно ли любое из вышеперечисленного, поэтому доверие не является автоматическим и применяется SOP. Разрешение должно быть предоставлено явно, прежде чем браузер предоставит данные, которые были переданы другому веб-сайту.


Расширения браузера, вкладка «Сеть» в инструментах разработчика браузера и приложения, такие как Postman, являются установленным программным обеспечением. Они не передают данные с одного сайта на JavaScript, принадлежащий другому сайту только потому, что вы посетили этот другой сайт. Установка программного обеспечения обычно требует более осознанного выбора.

Нет третьей стороны (Мэллори), которая считается риском.


Существует ряд обстоятельств, когда сайт Мэллори может заставить браузер получать данные от третьей стороны и отображать их (например, добавляя <img> элемент для отображения изображения). JavaScript Мэллори не может прочитать данные на этом ресурсе, хотя это может сделать только браузер Алисы и сервер Боба, поэтому он по-прежнему безопасен.


Access-Control-Allow-Origin заголовок, указанный в сообщении об ошибке, является частью CORS стандарт, который позволяет Бобу явно разрешить сайту Мэллори доступ к данным через браузер Алисы.

Базовая реализация будет просто включать:

Access-Control-Allow-Origin: *

… Разрешить любому веб-сайту читать данные.

Access-Control-Allow-Origin: http://example.com/

… Позволит только определенный сайт получить к нему доступ, и вы можете динамически генерировать это на основе Origin запрос заголовок, чтобы разрешить доступ к нему нескольким, но не всем сайтам.

Особенности того, как вы устанавливаете этот заголовок ответа, зависят от HTTP-сервера Боба и / или языка программирования на стороне сервера. Есть коллекция направляющих для различных общих конфигураций это может помочь.

Модель применения правил CORS

NB: некоторые запросы сложны и отправляют предполетный ОПЦИИ запрашивают у сервера ответ до того, как браузер отправит запрос GET / POST / PUT / Wh независимо от того, что JS хочет сделать. Реализации CORS, которые только добавляют Access-Control-Allow-Origin на определенные URL-адреса часто получают путаницу из-за этого.


Очевидно, что предоставление разрешения через CORS — это то, что Боб сделал бы, только если либо:

  • Данные не были частными или же
  • Мэллори доверяли

Если вы также являетесь Бобом в этом сценарии, то особенности того, как вы добавите заголовки разрешений CORS, будут зависеть от некоторой комбинации вашего выбора программного обеспечения сервера HTTP и того, какой язык вы используете для программирования на стороне сервера (если есть).

Маллори не может добавить этот заголовок, потому что она должна получить разрешение с сайта Боба, и было бы глупо (вплоть до того, чтобы сделать SOP бесполезным), чтобы она могла дать себе разрешение.


Некоторые запросы перекрестного происхождения preflighted.

Это происходит, когда (грубо говоря) вы пытаетесь сделать перекрестный запрос, который:

  • Включает учетные данные, такие как куки
  • Не может быть сгенерировано с помощью обычной формы HTML (например, имеет пользовательские заголовки или тип контента, который вы не можете использовать в форме enctype).

Обратите внимание, что «пользовательские заголовки» включают Access-Control-Allow-Origin и другие заголовки ответа CORS. Они не относятся к запросу, не делают ничего полезного (какой смысл в системе разрешений, где вы можете предоставить себе разрешение?) И должны появляться только в ответе.

В этих случаях тогда остальная часть этого ответа все еще применяется но вы также должны убедиться, что сервер может прослушивать предварительный запрос (который будет OPTIONS (и не GET, POST или что вы пытались отправить) и ответить на него с правами Access-Control-Allow-Origin заголовок, но также Access-Control-Allow-Methods а также Access-Control-Allow-Headers чтобы разрешить ваши конкретные методы HTTP или заголовки.


JSONP

Боб может также предоставить данные, используя взломать как JSONP именно так люди делали Ajax перекрестного происхождения до появления CORS.

Он работает, представляя данные в форме JavaScript-программы, которая вводит данные на страницу Мэллори.

Это требует, чтобы Мэллори доверяла Бобу, чтобы он не предоставлял вредоносный код.

Обратите внимание на общую тему: сайт, предоставляющий данные, должен сообщить браузеру, что сторонний сайт может получить доступ к данным, которые он отправляет в браузер.

Поскольку JSONP работает путем добавления <script> элемент для загрузки данных в форме JavaScript-программы, которая вызывает функцию, уже находящуюся на странице, пытаясь использовать технику JSONP для URL, который возвращает JSON, не удастся — как правило, с ошибкой CORB — потому что JSON не является JavaScript.

Переместите два ресурса в один источник

Если документ HTML, в котором запускается JS, и запрашиваемый URL-адрес находятся в одном источнике (с одинаковой схемой, именем хоста и портом), то по умолчанию политика разрешений в них совпадает. CORS не нужен.

Прокси

Маллори мог используйте серверный код для извлечения данных (которые она могла бы затем передать со своего сервера в браузер Алисы через HTTP, как обычно).

Это будет либо:

  • добавить заголовки CORS
  • преобразовать ответ в JSONP
  • существуют в том же источнике, что и HTML-документ

Этот серверный код может быть размещен третьей стороной (например, YQL).

Бобу не нужно было давать никаких разрешений для этого.

Это было бы хорошо, так как это только между Мэллори и Бобом. Боб не может думать, что Мэллори — Алиса, и предоставлять Мэллори данные, которые должны храниться в секрете между Алисой и Бобом.

Следовательно, Мэллори может использовать эту технику только для чтения общественности данные.

Написание чего-то другого, кроме веб-приложения

Как отмечено в разделе «Почему одна и та же политика происхождения применяется только к JavaScript на веб-странице», вы можете избежать SOP, не записывая JavaScript на веб-странице.

Это не значит, что вы не можете продолжать использовать JavaScript и HTML, но вы можете распространять их, используя какой-то другой механизм, такой как Node-WebKit или PhoneGap.

Расширение браузера может добавить заголовки CORS в ответ до применения той же политики происхождения.

Они могут быть полезны для разработки, но непрактичны для рабочего сайта (необоснованно просить каждого пользователя вашего сайта установить расширение для браузера, которое отключает функцию безопасности их браузера).

Они также имеют тенденцию работать только с простыми запросами (сбой при обработке предварительных запросов OPTIONS).

Наличие надлежащей среды разработки с местным развитием сервер
обычно лучший подход.


Обратите внимание, что SOP / CORS не смягчают XSS, CSRF, или же SQL-инъекция атаки, которые нужно обрабатывать самостоятельно.


  • Там нет ничего, что вы можете сделать в ваш код на стороне клиента, который позволит CORS получить доступ к кому-либо либо еще, сервер.
  • Если вы управляете сервером, запрос делается: Добавьте к нему разрешения CORS.
  • Если вы дружите с человеком, который его контролирует: попросите его добавить к нему разрешения CORS.
  • Если это общедоступная служба: прочтите документацию по API, чтобы узнать, что они говорят о доступе к ней с помощью клиентского JavaScript. Они могут сказать вам, чтобы использовать определенные URL-адреса или использовать JSONP (или они могут не поддерживать его вообще).
  • Если ничего из вышеперечисленного не применимо: получите браузер для общения ваш вместо сервера, а затем попросите ваш сервер получить данные с другого сервера и передать их. (Существуют также сторонние размещенные сервисы, которые прикрепляют заголовки CORS к общедоступным ресурсам, которые вы можете использовать).
100

Другие решения

Это происходит из-за ошибки CORS. CORS расшифровывается как Cross Source Resource Sharing. Проще говоря, эта ошибка возникает, когда мы пытаемся получить доступ к домену / ресурсу из другого домена.

Об этом подробнее здесь: CORS ошибка с JQuery

Чтобы это исправить, если у вас есть доступ к другому домену, вам потребуется разрешить Access-Control-Allow-Origin на сервере. Это можно добавить в заголовки. Вы можете включить это для всех запросов / доменов или определенного домена.

Как заставить работать пост-запрос совместного использования ресурсов между источниками (CORS)

Эти ссылки могут помочь

2

Целевой сервер должен разрешить перекрестный запрос. Чтобы разрешить его через экспресс, просто обработайте запрос http options:

app.options('/url...', function(req, res, next){
res.header('Access-Control-Allow-Origin', "*");
res.header('Access-Control-Allow-Methods', 'POST');
res.header("Access-Control-Allow-Headers", "accept, content-type");
res.header("Access-Control-Max-Age", "1728000");
return res.sendStatus(200);
});
2

Как это не упоминается в принятом ответе.

  • Это не тот случай для этого точного вопроса, но может помочь другим, которые ищут эту проблему
  • Это то, что вы можете сделать в своем клиентском коде, чтобы предотвратить ошибки CORS в некоторые случаи.

Вы можете использовать Простые Запросы.
Чтобы выполнить «простые запросы», запрос должен соответствовать нескольким условиям. Например. только позволяя POST, GET а также HEAD метод, а также разрешить только некоторые данные заголовки (вы можете найти все условия Вот).

Если ваш клиентский код не устанавливает явные заголовки (например, «Принять») с фиксированным значением в запросе, может быть случается, что некоторые клиенты устанавливают эти заголовки автоматически с некоторыми «нестандартными» значениями, в результате чего сервер не принимает его как простой запрос, что приведет к ошибке CORS.

2

Эта проблема CORS не получила дальнейшего развития (по другим причинам).

У меня эта проблема в настоящее время по другой причине.
Мой интерфейс также возвращает ошибку заголовка «Access-Control-Allow-Origin».

Просто я указал неправильный URL, поэтому этот заголовок не был отражен должным образом (в котором я предположил, что он это сделал). localhost (внешний интерфейс) -> вызов незащищенного http (должен быть https), убедитесь, что конечная точка API от внешнего интерфейса указывает на правильный протокол.

0

Вы должны включить CORS, чтобы он заработал.

-3
По вопросам рекламы [email protected]