Как работает заголовок Access-Control-Allow-Origin?


видимо, я совершенно неправильно понял его слова. Я подумал о чем-то вроде этого:

  1. клиент загружает код javascript MyCode.js от http://siteA -источник.
  2. заголовок ответа MyCode.Яш содержит Access-Control-Allow-Origin: http://siteB, который я думал, что означает, что MyCode.js было разрешено делать перекрестные ссылки на сайт B.
  3. клиент запускает некоторые функции Mycode в.js, которые в свою очередь делают запросы к http://siteB, что должно быть хорошо, несмотря на то, что запросы кросс-происхождения.

Ну, я ошибаюсь. Это совсем не так работает. Итак, я прочитал Кросс-происхождения совместное использование ресурсов и попытался читать совместное использование ресурсов из разных источников в рекомендации w3c

одно точно - я до сих пор не понимаю, как я должен использовать этот заголовок.

У меня есть полный контроль сайт A и сайт B. Как включить код javascript, загруженный с сайта A, для доступа к ресурсам на сайте B с помощью этого заголовка?

П. С.

Я не хочу использовать JSONP.

11 825

11 ответов:

Access-Control-Allow-Origin это CORS (Cross-Origin Resource Sharing) заголовок.

когда сайт A пытается получить контент с сайта B, сайт B может отправить Access-Control-Allow-Origin заголовок ответа, чтобы сообщить браузеру, что содержимое этой страницы доступна в определенное происхождение. (Ан происхождения это домен, плюс схема и номер порта.) По умолчанию страницы сайта " В " составляет недоступно для любого другого источника; через Access-Control-Allow-Origin заголовок открывает a дверь для перекрестного доступа происхождения специфическим запрашивая происхождением.

для каждого ресурса/страницы, который Сайт B хочет сделать доступным для сайта A, сайт B должен обслуживать свои страницы с заголовком ответа:

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

современные браузеры не будут блокировать междоменные запросы напрямую. Если сайт A запрашивает страницу с сайта B, браузер фактически получит запрошенную страницу на сетевом уровне и проверьте, есть ли в заголовках ответов список сайта A как разрешенный домен отправителя. Если сайт B не указал, что сайту A разрешен доступ к этой странице, браузер запустит XMLHttpRequest ' s error событие и отклонить данные ответа на запрос кода JavaScript.

не простые запросы

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

  • использование HTTP-глагола, отличного от GET или POST (например, PUT, DELETE)
  • использование не простых заголовков запросов; единственными простыми заголовками запросов являются:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (это просто только тогда, когда его значение application/x-www-form-urlencoded,multipart/form-data, или text/plain)

если сервер отвечает на параметры preflight с соответствующими заголовками ответа (Access-Control-Allow-Headers для не простых заголовков,Access-Control-Allow-Methods для не простых глаголов), которые соответствуют не простой глагол и/или не простые заголовки, то браузер отправляет фактический запрос.

предположим, что сайт A хочет отправить запрос PUT для /somePage С не-простой Content-Type стоимостью application/json браузер будет сначала отправить предварительный запрос:

OPTIONS /somePage HTTP/1.1
Origin: http://siteA.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

отметим, что Access-Control-Request-Method и Access-Control-Request-Headers добавляются браузером автоматически; вам не нужно добавлять их. Эта опция preflight получает успешные заголовки ответов:

Access-Control-Allow-Origin: http://siteA.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type

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

браузеры отправляют фактический запрос:

PUT /somePage HTTP/1.1
Origin: http://siteA.com
Content-Type: application/json

{ "myRequestContent": "JSON is so great" }

и сервер отправляет обратно Access-Control-Allow-Origin так же, как и для простого запроса:

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

посмотреть понимание XMLHttpRequest над CORS для получения дополнительной информации о непростых запросах.

Совместное Использование Запросов Кросс-Происхождения -CORS (A. K. A. Междоменный AJAX-запрос)-это проблема, с которой может столкнуться большинство веб-разработчиков, в соответствии с политикой того же происхождения браузеры ограничивают клиентский JavaScript в песочнице безопасности, обычно JS не может напрямую взаимодействовать с удаленным сервером из другого домена. В прошлом разработчики создали много сложных способов для достижения междоменного запроса ресурсов, чаще всего используя следующие способы:

  1. использование Flash/Silverlight или на стороне сервера как "прокси" для общения с пульта дистанционного управления.
  2. JSON с прокладкой (JSONP).
  3. встраивает удаленный сервер в iframe и связывается через фрагмент или window.name см.здесь.

эти хитрые способы имеют более или менее некоторые проблемы, например JSONP может привести к дыре в безопасности, если разработчики просто "eval" его, и #3 выше, хотя он работает, оба домена должны строить строгий контракт между собой, это ни гибкий и элегантный ИМХО:)

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

Механизм

С высокого уровня мы можем просто считать CORS-это контракт между клиентским AJAX-вызовом из домена A и страницей, размещенной на домене B, типичный запрос/ответ Кросс-происхождения будет:

DomainA AJAX запрос заголовки

Host DomainB.com
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json
Accept-Language en-us;
Accept-Encoding gzip, deflate
Keep-Alive 115
Origin http://DomainA.com 

заголовки ответов DomainB

Cache-Control private
Content-Type application/json; charset=utf-8
Access-Control-Allow-Origin DomainA.com
Content-Length 87
Proxy-Connection Keep-Alive
Connection Keep-Alive

синие части, отмеченные выше, были фактами ядра, заголовок запроса "Origin" указывает, откуда исходит запрос перекрестного происхождения или запрос перед полетом", заголовок ответа" Access-Control-Allow-Origin " указывает, что эта страница разрешает удаленный запрос из DomainA (если значение * указывает, что позволяет удаленные запросы из любого домена).

как я уже упоминал выше, W3 рекомендуется браузер для реализации "предварительный запрос " перед отправкой фактически перекрестного HTTP-запроса, в двух словах это HTTP OPTIONS запрос:

OPTIONS DomainB.com/foo.aspx HTTP/1.1

если Foo.aspx поддерживает параметры HTTP verb, он может вернуть ответ, как показано ниже:

HTTP/1.1 200 OK
Date: Wed, 01 Mar 2011 15:38:19 GMT
Access-Control-Allow-Origin: http://DomainA.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, HEAD
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Max-Age: 1728000
Connection: Keep-Alive
Content-Type: application/json

только если ответ содержит "Access-Control-Allow-Origin" и его значение " * " или содержит домен, который отправил запрос CORS, выполнив это обязательное условие браузер будет отправьте фактический Междоменный запрос и кэшируйте результат в "Предварительный Результат-Кэш".

я писал о CORS три года назад: AJAX Cross-Origin HTTP request

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

по данным этой Mozilla Developer Network article,

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

enter image description here

An HTML-страницы ежедневно с http://domain-a.com делает <img> src запрос на http://domain-b.com/image.jpg.
Многие страницы в интернете сегодня загружают ресурсы, такие как таблицы стилей CSS,изображения и скрипты из отдельных доменов (При этом должно быть прохладно).

Политика Того Же Происхождения

по соображениям безопасности, браузеры ограничивают кросс-происхождение HTTP запросы запускать из скриптов.
Для например, XMLHttpRequest и Fetch следуя политика того же происхождения.
Итак, веб-приложение с помощью XMLHttpRequest или Fetch можно только сделать HTTP-запросов до свой собственный домен.

совместное использование ресурсов из разных источников (CORS)

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

The совместное использование ресурсов из разных источников (CORS) механизм дает веб-сервера управление междоменным доступом, которые обеспечивают безопасную междоменную передачу данных.
Современные браузеры используют CORS на API container - например,XMLHttpRequest или Fetch - для снижения рисков перекрестных HTTP-запросов.

как работает CORS ()

Википедия:

стандарт CORS описывает новые заголовки HTTP, которые предоставляют браузеры и серверы способ запроса удаленные URL-адреса только тогда, когда у них есть разрешение.

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

пример

  1. браузер передает OPTIONS запрос .

    значение этого заголовка-это домен, который обслуживал родителя страница. Когда страница из http://www.example.com пытается получить доступ к данным пользователя в service.example.com следующий заголовок запроса будет направлен service.example.com:

    происхождение:http://www.example.com

  2. сервер service.example.com может реагировать с:

    • An Access-Control-Allow-Origin (ACAO) заголовок в своем ответе, указывающий, какие исходные сайты разрешены.
      Например:

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

    • страница ошибки, если сервер не разрешает кросс-доменный запрос

    • An Access-Control-Allow-Origin (ACAO) заголовок с подстановочным знаком, который позволяет все домены:

      Access-Control-Allow-Origin: *

Если вы хотите просто протестировать междоменное приложение, в котором браузер блокирует ваш запрос, то вы можете просто открыть браузер в небезопасном режиме и протестировать приложение без изменения кода и без создания небезопасного кода. Из MAC OS вы можете сделать это из терминальной линии:

open -a Google\ Chrome --args --disable-web-security --user-data-dir

используя реагировать и Axios, присоедините прокси-ссылку к URL и добавьте заголовок, как показано ниже

https://cors-anywhere.herokuapp.com/ + Your API URL

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

axios.get(`https://cors-anywhere.herokuapp.com/[YOUR_API_URL]`,{headers: {'Access-Control-Allow-Origin': '*'}})
      .then(response => console.log(response:data);
  }

1. Клиент загружает код javascript MyCode.js от http://siteA - происхождение.

код, который выполняет загрузку-ваш тег html-скрипта или xhr из javascript или что - то еще-пришел, скажем, http://siteZ. И, когда браузер запрашивает MyCode.js, он отправляет заголовок Origin: с надписью " Origin:http://siteZ", потому что он может видеть, что вы просите siteA и siteZ != siteA. (Вы не можете остановиться или вмешайтесь в это.)

2. Заголовок ответа MyCode.js содержит Access-Control-Allow-Origin:http://siteB, который я думал, что означает, что MyCode.js было разрешено делать перекрестные ссылки на сайт B.

нет. Это означает, что только siteB может сделать этот запрос. Так что ваш запрос на MyCode.вместо этого js из siteZ получает ошибку, и браузер обычно ничего не дает. Но если вы заставите ваш сервер вернуть A-C-A-O: siteZ вместо этого вы получите MyCode.js . Или если он пошлет '*', это сработает, это впустит всех. Или если сервер всегда отправляет строку из заголовка Origin:... но... для обеспечения безопасности, если вы боитесь хакеров, ваш сервер должен разрешать только origins в коротком списке, которым разрешено делать эти запросы.

Тогда, MyCode.js приходит от siteA. Когда он делает запросы к siteB, все они являются перекрестными, браузер отправляет Origin: siteA, и siteB должен принять siteA, распознать он находится в коротком списке разрешенных запросов и отправляет обратно A-C-A-O: siteA. Только тогда браузер позволит вашему скрипту получить результат этих запросов.

Я работаю с express 4 и node 7.4 и angular,у меня была та же проблема, что и у меня:
a) на стороне сервера: в приложении file.js я даю заголовки для всех ответов, таких как:

app.use(function(req, res, next) {  
      res.header('Access-Control-Allow-Origin', req.headers.origin);
      res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
      next();
 });  

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

res.header("Access-Control-Allow-Headers","*");
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

но мне это не нужно,
b) на стороне клиента: в send ajax вам нужно добавить: "withCredentials: true", например:

$http({
     method: 'POST',
     url: 'url, 
     withCredentials: true,
     data : {}
   }).then(function(response){
        // code  
   }, function (response) {
         // code 
   });

удачи.

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

цель той же политики происхождения-защитить вас от вредоносного JavaScript на siteA.com доступ к личной информации, которую вы выбрали только для совместного использования siteB.com. без такой же политики происхождения, JavaScript написанный авторами siteA.com смог сделать Ваш браузер делает запросы к siteB.com, используя ваши аутентификационные куки для siteB.com таким образом, siteA.com может украсть секретную информацию, которой Вы делитесь siteA.com.

иногда вам нужно работать с кросс-доменом, в котором входит CORS. CORS ослабляет ту же политику происхождения для domainA.com, используя Access-Control-Allow-Origin заголовок для списка других доменов (domainB.com) которые доверяют запускать JavaScript, который может взаимодействовать с domainA.com.

чтобы понять, какой домен следует подавайте заголовки CORS, подумайте об этом. Вы посещаете malicious.com, который содержит код JavaScript, который пытается сделать запрос домен крест mybank.com. Оно должно быть mybank.com не malicious.com, чтобы решить, будет ли или не он устанавливает CORS-заголовки, которые расслабляют ту же политику происхождения, позволяющих JavaScript из malicious.com для взаимодействия с ним. Если бы это было возможно malicous.com чтобы установить собственные заголовки CORS, разрешающие собственный доступ к JavaScript mybank.com, это полностью аннулирует же происхождения политики.

Я думаю, что причиной моей плохой интуиции является точка зрения, которую я имею при разработке сайта. Его мой сайт со всеми мой JavaScript, поэтому он не делает ничего вредоносного, и он должен быть до меня чтобы указать, какие другие сайты мой JavaScript может взаимодействовать. Когда на самом деле я должен думать, что другое сайты JavaScript пытаются взаимодействовать с моим сайтом и должны Я использую CORS, чтобы позволить им?

Если вы используете PHP, попробуйте добавить следующий код при отбрасывании файла php:

Если вы используете localhost, попробуйте следующее:

header("Access-Control-Allow-Origin: *");

Если вы используете внешние Домены, такие как сервер, попробуйте следующее:

header("Access-Control-Allow-Origin: http://www.website.com");

для совместного использования перекрестного источника установите заголовок:'Access-Control-Allow-Origin':'*';

Php:header('Access-Control-Allow-Origin':'*');

узел: app.use('Access-Control-Allow-Origin':'*');

Это позволит обмениваться контентом для разных доменов.

в Python я использую Flask-CORS библиотека С большим успехом. Это делает работу с CORS очень легкой и безболезненной. Я добавил некоторый код из документации библиотеки ниже.

установка:

$ pip install -U flask-cors

простой пример, который позволяет CORS для всех доменов на всех маршрутах:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

более подробные примеры см. В документации. Я использовал простой пример выше, чтобы обойти проблему CORS в ионном приложении я здание, которое должно иметь доступ к отдельному серверу колб.