tl; dr - в конце есть сводка, а в ответе заголовки, чтобы было проще найти нужные части. Тем не менее, рекомендуется прочитать все, так как это дает полезную основу для понимания того, почему, это упрощает понимание того, как применяется в различных обстоятельствах.
О той же политике происхождения
Это та же политика происхождения . Это функция безопасности, реализованная браузерами.
В вашем конкретном случае показано, как он реализован для XMLHttpRequest (и вы получите идентичные результаты, если бы использовали выборку), но он также применяется к другим вещам (например, изображениям, загруженным в <canvas>
или документы, загруженные в <iframe>
), просто с немного разные реализации.
(Как ни странно, это также применимо к шрифтам CSS, но это потому, что найденные литейщики настаивали на DRM, а не на проблемах безопасности, которые обычно покрывает политика одинакового происхождения).
Стандартный сценарий, демонстрирующий необходимость СОП, можно продемонстрировать тремя символами :
- Алиса - это человек с веб-браузером
- Боб запускает веб-сайт (
https://www.[website].com/
в вашем примере)
- Мэллори запускает веб-сайт (
http://localhost:4300
в вашем примере)
Алиса вошла на сайт Боба и хранит там некоторые конфиденциальные данные. Возможно, это интрасеть компании (доступная только для браузеров в локальной сети) или ее онлайн-банкинг (доступный только с помощью файла cookie, который вы получаете после ввода имени пользователя и пароля).
Алиса посещает веб-сайт Мэллори, на котором есть некоторый JavaScript, который заставляет браузер Алисы делать HTTP-запрос на веб-сайт Боба (с ее IP-адреса с ее файлами cookie и т. Д.). Это может быть так же просто, как использовать XMLHttpRequest
и читать responseText
.
Политика одинакового происхождения браузера не позволяет этому JavaScript читать данные, возвращаемые веб-сайтом Боба (к которым Боб и Алиса не хотят, чтобы Мэллори имел доступ). (Обратите внимание , что вы можете, например, отобразить изображение с помощью <img>
элемента по происхождению , так как содержание изображения не подвергаются JavaScript (или Mallory) ... если вы не бросить холст в смесь , в этом случае вы будете генерировать один и то же происхождение ошибка нарушения).
Почему применяется та же политика происхождения, если вы не думаете, что это должно быть
Для любого заданного URL-адреса возможно, что СОП не требуется. Вот несколько распространенных сценариев, когда это так:
- Алиса, Боб и Мэллори - одно и то же лицо.
- Боб предоставляет полностью общедоступную информацию
… Но браузер не имеет возможности узнать, верно ли что-либо из вышеперечисленного, поэтому доверие не является автоматическим, и применяется СОП. Разрешение должно быть предоставлено явным образом, прежде чем браузер передаст данные другому веб-сайту.
Почему одна и та же политика происхождения применяется только к JavaScript на веб-странице
Расширения браузера *
, вкладка «Сеть» в инструментах разработчика браузера и такие приложения, как Postman, являются установленным программным обеспечением. Они не передают данные с одного веб-сайта в JavaScript, принадлежащий другому веб-сайту, только потому, что вы посетили этот другой веб-сайт . Установка программного обеспечения обычно требует более осознанного выбора.
Нет третьей стороны (Мэллори), которая считается риском.
*
Расширения браузера нужно писать осторожно, чтобы избежать проблем с перекрестным происхождением. См., Например, документацию Chrome .
Почему вы можете отображать данные на странице, не читая их с помощью JS
Существует ряд обстоятельств, при которых сайт Мэллори может заставить браузер получать данные от третьей стороны и отображать их (например, путем добавления <img>
элемента для отображения изображения). Однако JavaScript Мэллори не может прочитать данные в этом ресурсе, это могут сделать только браузер Алисы и сервер Боба, поэтому он по-прежнему безопасен.
CORS
Access-Control-Allow-Origin
HTTP ответ заголовок , предусмотренный в сообщении об ошибке является частью CORS стандарта , что позволяет Бобу явным образом предоставить разрешение на сайт Мэллорите , чтобы получить доступ к данным через браузер Алисы.
Базовая реализация будет просто включать:
Access-Control-Allow-Origin: *
… В заголовках ответов, чтобы любой веб-сайт мог читать данные.
Access-Control-Allow-Origin: http://example.com/
… Позволит только определенному сайту получить к нему доступ, и Боб может динамически генерировать его на основе заголовка Origin
запроса, чтобы разрешить доступ к нему нескольким, но не всем сайтам.
Специфика того, как Боб устанавливает этот заголовок ответа, зависит от HTTP-сервера Боба и / или серверного языка программирования. Есть набор руководств по различным распространенным конфигурациям, которые могут помочь.
NB: Некоторые запросы являются комплексными и отправить предполетной OPTIONS запросить, чтобы сервер должен будет реагировать раньше браузер отправит GET / POST / PUT / Whatever запрос о том , что JS хочет сделать. Реализации CORS, которые добавляются только Access-Control-Allow-Origin
к определенным URL-адресам, часто сбиваются с толку.
Очевидно, что предоставление разрешения через CORS - это то, что Боб сделал бы только в том случае, если:
- Данные не были личными или
- Мэллори доверяли
Но я не Боб!
У Мэллори нет стандартного механизма для добавления этого заголовка, потому что он должен поступать с веб-сайта Боба, который она не контролирует.
Если Боб запускает общедоступный API, то может быть механизм для включения CORS (возможно, путем форматирования запроса определенным образом или параметра конфигурации после входа на сайт портала разработчика для сайта Боба). Однако это должен быть механизм, реализованный Бобом. Мэллори может прочитать документацию на сайте Боба, чтобы узнать, доступно ли что-нибудь, или она может поговорить с Бобом и попросить его внедрить CORS.
Сообщения об ошибках, в которых упоминается "Ответ на предполетную проверку"
Некоторые запросы на перекрестное происхождение проходят предварительную проверку .
Это происходит, когда (грубо говоря) вы пытаетесь сделать запрос на другой источник, который:
- Включает учетные данные, такие как файлы cookie
- Невозможно сгенерировать с помощью обычной HTML-формы (например, с настраиваемыми заголовками или Content-Type, которые нельзя использовать в форме
enctype
).
Если вы правильно делаете что-то, что требует предполетной подготовки
В этих случаях , то остальная часть этого ответа все еще применяется , но вы также должны убедиться , что сервер может прослушивать предполетной запрос (который будет OPTIONS
(а не GET
, POST
или что вы пытаетесь отправить) и ответить на него с правом Access-Control-Allow-Origin
header, но также 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 на веб-странице», вы можете избежать использования СОП, не написав JavaScript на веб-странице.
Это не означает, что вы не можете продолжать использовать JavaScript и HTML, но вы можете распространять их, используя какой-либо другой механизм, например Node-WebKit или PhoneGap.
Расширения браузера
Расширение браузера может вставлять заголовки CORS в ответ до того, как будет применена политика того же происхождения.
Они могут быть полезны для разработки, но непрактичны для производственного сайта (неразумно просить каждого пользователя вашего сайта установить расширение, отключающее функцию безопасности его браузера).
Они также обычно работают только с простыми запросами (сбой при обработке предполетных запросов OPTIONS).
Обычно лучше иметь подходящую среду разработки с локальным сервером разработки .
Прочие риски безопасности
Обратите внимание, что SOP / CORS не смягчают атаки XSS , CSRF или SQL Injection, которые необходимо обрабатывать независимо.
Резюме
- Там нет ничего , что вы можете сделать в вашей стороне клиента код , который позволит CORS доступ к кто - либо серверу.
- Если вы управляете сервером, выполняется запрос к: Добавьте к нему разрешения CORS.
- Если вы дружите с человеком, который его контролирует: попросите его добавить к нему разрешения CORS.
- Если это государственная услуга:
- Прочтите их документацию по API, чтобы узнать, что они говорят о доступе к нему с помощью клиентского JavaScript:
- Они могут посоветовать вам использовать определенные URL-адреса
- Они могут поддерживать JSONP
- Они могут вообще не поддерживать доступ между источниками из клиентского кода (это может быть осознанное решение по соображениям безопасности, особенно если вам необходимо передавать персонализированный ключ API в каждом запросе).
- Убедитесь, что вы не инициируете предполетный запрос, который вам не нужен. API может предоставлять разрешение для простых запросов, но не для предварительных запросов.
- Если ничего из вышеперечисленного не применимо: вместо этого попросите браузер взаимодействовать с вашим сервером, а затем пусть ваш сервер получает данные с другого сервера и передает их. (Существуют также сторонние размещенные службы, которые прикрепляют заголовки CORS к общедоступным ресурсам, которые вы можете использовать).