XMLHttpRequest не может загрузить XXX нет заголовка " Access-Control-Allow-Origin


tl; dr; о той же политике происхождения

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

XMLHttpRequest не удается загрузить https://www.example.com/ В запрошенном заголовке отсутствует заголовок " Access-Control-Allow-Origin ресурс. Происхождение'http://localhost:4300', следовательно, не разрешен доступ.

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

6 53

6 ответов:

о той же политике происхождения

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

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

в стандартный сценарий, демонстрирующий необходимость SOP, можно продемонстрировать с помощью трех символов:

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

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

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

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


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

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

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

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


почему Та же политика происхождения применяется только к JavaScript на веб-странице

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

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


почему вы можете отображать данные на странице, не читая его с помощью JS

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


CORS

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

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

Access-Control-Allow-Origin: *

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

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

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

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

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


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

  • данные не были приватными или
  • Мэллори был надежным

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

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


сообщения об ошибках, которые упоминают "Ответ для предполетной подготовки"

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

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

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

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

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


альтернативы CORS

JSONP

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

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

он требует, чтобы Mallory trust Bob не предоставлял вредоносный код.

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

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

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

Прокси

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

- это:

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

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

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

это было бы прекрасно, так как это только между Мэллори и Боб. У Боба нет возможности думать, что Мэллори-это Алиса, и предоставить Мэллори данные, которые должны быть конфиденциальными между Алисой и Бобом.

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

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

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

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

браузер расширения

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

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

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

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


другие угрозы безопасности

обратите внимание, что SOP / CORS не смягчают XSS, CSRF или SQL Injection атаки, которые должны быть обработаны независимо.


резюме

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

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

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

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

как получить кросс-происхождения совместное использование ресурсов (ПДБС) пост запрос работающего

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

целевой сервер должен разрешать перекрестный запрос. Чтобы разрешить его через express, просто обработайте запрос 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);
});

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

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

если владелец сервера явно не предотвращает его каким - либо образом-вы можете использовать простые запросы.
обратите внимание, что 'простые вопросы' нужно выполнить несколько условий, в том числе только разрешение POST,GET и HEAD а также позволяет только некоторые заданные заголовки (вы можете найти все условия здесь).

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

хорошим индикатором для этого сценария может быть ошибка CORS, включая термин preflight.

этой это связанный вопрос здесь на stackoverflow.

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

в случае, если вы получаете эту ошибку при разработке расширения для google chrome, просто добавьте-

  "permissions": [
"http://www.google.com/"

]

в манифесте.файл json.
** замените Google на свой сторонний URL.