Та же политика происхождения
В 1995 году компания Netscape ввела гомологичную политику в браузер. В настоящее время эта политика реализована во всех браузерах.
Первоначально его значение означало, что файл cookie, установленный веб-страницей A и веб-страницей B, не может быть открыт, если только эти две веб-страницы не имеют «одного и того же происхождения». Так называемый «гомологичный» относится к «трем идентичным»:
- тот же протокол
- такое же доменное имя
- тот же порт
Цель политики единого источника — обеспечить безопасность пользовательской информации и предотвратить кражу данных вредоносными веб-сайтами.
Представьте ситуацию: веб-сайт А — это банк.После того как пользователь входит в систему, веб-сайт А устанавливает файл cookie на компьютере пользователя, который содержит некоторую личную информацию (например, общую сумму депозитов). После того, как пользователь покидает веб-сайт A, он снова посещает веб-сайт B. Если нет ограничения на одно и то же происхождение, веб-сайт B может прочитать файл cookie веб-сайта A, и информация о конфиденциальности будет раскрыта. Еще более пугающим является то, что файлы cookie часто используются для сохранения статуса входа пользователя в систему.Если пользователь не выходит из системы, другие веб-сайты могут притворяться пользователем и делать все, что захотят. Потому что браузеры также оговаривают, что отправка форм не подпадает под действие политики одного и того же происхождения.
Видно, что требуется политика одного и того же происхождения, иначе файлы cookie могут использоваться совместно, и Интернет будет небезопасным.
С развитием Интернета политика одного и того же происхождения становится все более и более строгой. В настоящее время в общей сложности три поведения ограничены, если они не гомологичны.
- Невозможно получить файлы cookie, localstorage и indexedDB для веб-страниц с разными источниками.
- Невозможно получить доступ к DOM (iframe) веб-страниц из разных источников.
- Не удается отправить запросы AJAX или запросы на выборку на разные адреса (могут быть отправлены, но браузер отказывается принимать ответ).
Междоменный Ajax
Политика одного и того же происхождения браузера приведет к междоменному, то есть, если есть другой протокол, доменное имя или порт, он считается другим доменом, и Ajax не может использоваться для отправки HTTP-запросов на серверы другого происхождения. . В первую очередь необходимо уточнить вопрос, запрос междоменный, запрос отправлен? Ответ: да, он был отправлен, но браузер перехватил ответ.
Зачем нужен междоменный
Политика Ajax в отношении того же происхождения в основном направлена на предотвращениеCSRF
Атака (подделка межсайтового запроса), если нет политики одного и того же происхождения AJAX, это довольно опасно.Каждый HTTP-запрос, который мы инициируем, будет приносить файл cookie, соответствующий адресу запроса, тогда могут быть выполнены следующие атаки:
- Пользователь вошел на страницу своего банкаmybank.com,mybank.com добавляет идентификатор пользователя в файл cookie пользователя.
- Пользователь просматривает вредоносную страницуevil.com. Выполняется вредоносный код запроса AJAX на странице.
- evil.com на http://mybank.com инициирует HTTP-запрос AJAX, и запрос по умолчанию одновременно отправляет файл cookie, соответствующий http://mybank.com.
- Страница банка извлекает идентификатор пользователя из отправленного файла cookie, проверяет правильность пользователя и возвращает данные запроса в ответе. В этот момент происходит утечка данных.
- А поскольку Ajax выполняется в фоновом режиме, пользователь не может воспринимать этот процесс.
То же самое относится и к политике одинакового происхождения DOM, еслиiframe
Между междоменным доступом, чтобы вы могли атаковать:
- Создайте поддельный веб-сайт с банковским веб-сайтом, вложенным в iframe.mybank.com.
- Настройте ширину и высоту iframe на всю страницу, чтобы пользователи заходили кроме имени домена, а остальная часть ничем не отличалась от сайта банка.
- В это время, если пользователь вводит пароль учетной записи, наш основной веб-сайт может получить междоменный доступ к узлу dom http://mybank.com, и вход пользователя может быть получен, после чего атака завершена.
Следовательно, с междоменными и междоменными ограничениями мы можем более безопасно путешествовать по Интернету.
междоменное решение
CORS
CORS является стандартным стандартом W3C, подписчиты для совместного использования ресурсов ресурсов (совместное использование ресурсов перекрестного происхождения), которое позволяет браузеру пересекать исходный сервер, выдавать запрос XMLHTTPREQUEST.
Весь процесс связи CORS автоматически завершается браузером и не требует участия пользователя. Для разработчиков связь CORS ничем не отличается от обычной связи AJAX, и код точно такой же. Как только браузер обнаружит, что запрос AJAX является междоменным, он автоматически добавит некоторую дополнительную информацию в заголовок, а иногда будет сделан дополнительный запрос, но пользователь не будет знать об этом. Таким образом, ключом к реализации связи CORS является сервер. Междоменная связь возможна, если сервер реализует интерфейс CORS.
Конфигурация на стороне сервера
Обычно используемые элементы конфигурации CORS:
-
Access-Control-Allow-Origin(обязательно) – Разрешенные доменные имена, заполните только
*
(подстановочный знак) или одно доменное имя. -
Access-Control-Allow-Methods(обязательно) — это позволяет использовать метод http для запросов между источниками (общий с
POST、GET、OPTIONS
). -
Access-Control-Allow-Headers(когда предварительный запрос содержит
Access-Control-Request-Headers
необходимо включить) - это по предварительному запросуAccess-Control-Request-Headers
Ответ, как и выше, представляет собой список всех поддерживаемых заголовков, разделенных запятыми, которые могут быть возвращены. -
Access-Control-Allow-Credentials(необязательно) — указывает, разрешить ли отправку файлов cookie, существует только одно необязательное значение: true (должно быть в нижнем регистре). Если файлы cookie не включены, опустите это вместо false. Этот элемент связан с элементом в объекте XmlHttpRequest.
withCredentials
Свойства должны быть непротиворечивыми, то есть, когда withCredentials имеет значение true, этот элемент также является истинным, когда withCredentials имеет значение false, этот элемент опускается и не записывается. В противном случае запрос не будет выполнен. -
Access-Control-Max-Age(необязательно) – время кэширования в секундах. В течение допустимого времени браузеру не нужно снова инициировать предварительный запрос для того же самого запроса.
Процесс междоменного определения CORS
-
Браузер сначала сопоставляет интерфейсную страницу и внутренний адрес взаимодействия в соответствии с политикой одного и того же источника. Если источник один и тот же, запрос данных отправляется напрямую, если источник отличается, междоменный запрос послал.
-
После того, как сервер получает междоменный запрос браузера, он возвращает соответствующий заголовок файла в соответствии со своей конфигурацией. Если не разрешен междоменный доступ, заголовок файла не содержит
Access-Control-Allow-origin
поле, если доменное имя было настроено, оно будет возвращеноAccess-Control-Allow-origin + 对应配置规则里的域名的方式
. -
Браузер получает заголовок ответа в соответствии с полученным
Access-Control-Allow-origin
Поле совпадает, если такого поля нет, то это означает, что кросс-доменность не разрешена, и выдается ошибка, если это поле есть, то содержимое поля сравнивается с текущим доменным именем. один и тот же источник, значит, междоменный разрешен, и браузер принимает ответ; если источник другой, это означает, что доменное имя не является междоменным, браузер не принимает ответ и выдает ошибку .
Вывод консоли отличается для двух типов ошибок, упомянутых выше:
- Сервер разрешает междоменные запросы, но источник, указанный Origin, не входит в разрешенную область, и сервер возвращает обычный HTTP-ответ. Браузер обнаружил, что информация заголовка этого ответа не содержит
Access-Control-Allow-Origin
поле, вы знаете, что что-то пошло не так, поэтому выдается ошибка, которая перехватывается функцией обратного вызова onerror XMLHttpRequest. Обратите внимание, что этот тип ошибки не может быть идентифицирован по коду состояния, так как код состояния ответа HTTP может быть 200.
<!--控制台返回结果-->
XMLHttpRequest cannot load http://localhost/city.json.
The 'Access-Control-Allow-Origin' header has a value 'http://segmentfault.com' that is not equal to the supplied origin.
Origin 'http://www.zhihu.com' is therefore notallowed access.
- Сервер не разрешает любые запросы между источниками
<!--控制台返回结果-->
XMLHttpRequest cannot load http://localhost/city.json.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://www.zhihu.com' is therefore not allowed access.
простой запрос
Фактически браузеры делят запросы CORS на две категории: простые запросы (simple request
) и непростые запросы (not-so-simple request
).
Простой запрос означает выполнение следующих условий (обычно учитываются только первые два условия):
- использовать
GET、POST、HEAD
Один из методов запроса. - Информация заголовка HTTP не превышает следующих полей:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type: ограничено тремя значениями
application/x-www-form-urlencoded、multipart/form-data、text/plain
- Ни один из объектов XMLHttpRequestUpload в запросе не зарегистрировал ни одного прослушивателя событий;
- Доступ к объектам XMLHttpRequestUpload можно получить с помощью свойства XMLHttpRequest.upload. В запросе не использовался объект ReadableStream.
Для простых запросов браузер напрямую инициирует запрос CORS.origin
поля (включая протокол + имя домена + порт), чтобы решить, соглашаться ли на этот запрос.
еслиorigin
Если указанный источник находится в допустимом диапазоне, ответ, возвращаемый сервером, будет иметь несколько дополнительных полей заголовка:
Access-Control-Allow-Origin: http://xxx.xxx.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
не простой запрос
Непростые запросы относятся к тем запросам, которые имеют особые требования к серверу, такие как метод запроса.put
илиdelete
,илиcontent-type
Типapplication/json
. На самом деле, кроме простых запросов есть непростые запросы.
Запросы CORS, которые не являются простыми запросами, будут использоваться перед официальным общением.OPTIONS
Метод инициирует предварительный запрос к серверу.Браузер сначала запрашивает сервер, находится ли доменное имя текущей страницы в списке разрешенных сервером и какие HTTP-команды и поля заголовка можно использовать. Браузер выдаст формальный запрос XMLHttpRequest только в случае положительного ответа, в противном случае он сообщит об ошибке.
Вот заголовок предварительного запроса:
OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
После того как сервер передаст «предварительный» запрос, каждый последующий обычный CORS-запрос браузера будет таким же, как и простой запрос.
Почему существуют простые запросы и непростые запросы, см. ответ на Zhihu.Почему междоменные почтовые запросы делятся на простые запросы и непростые запросы, связанные с типом контента?
JSONP
Принцип JSONP заключается в использовании<script>
Атрибут src тега не имеет междоменных ограничений.Указывая на адрес, к которому необходимо получить доступ, сервер возвращает предопределенный вызов функции Javascript и передает серверу данные в виде параметра функции.Этот метод требуется интерфейс и серверная часть Сотрудничество завершено.
//定义获取数据的回调方法
function getData(data) {
console.log(data);
}
// 创建一个script标签,并且告诉后端回调函数名叫 getData
var body = document.getElementsByTagName('body')[0];
var script = document.gerElement('script');
script.type = 'text/javasctipt';
script.src = 'demo.js?callback=getData';
body.appendChild(script);
//script 加载完毕之后从页面中删除,否则每次点击生成许多script标签
script.onload = function () {
document.body.removeChild(script);
}
JSONP прост в использовании и имеет хорошую совместимость, но ограничен толькоget
просить.
прокси сервера
У браузера есть междоменные ограничения, но у сервера нет междоменных проблем, поэтому сервер может запросить ресурсы нужного домена и вернуть их клиенту.
Как правило, мы используем его при разработке локальной среды.webpack-dev-server
Запустите службу локально для доступа через прокси.
document.domain
Этот метод можно использовать только в том случае, если доменные имена второго уровня совпадают, напримерa.test.com
а такжеb.test.com
относится к этому методу.
Просто добавьте на обе страницыdocument.domain = 'test.com'
, сквозьa.test.com
Создаватьiframe
, контролироватьiframe
изwindow
, взаимодействовать.
postMessage
window.postMessage — это API HTML5, который позволяет междоменную отправку сообщений между двумя окнами.
Этот метод часто используется для получения данных сторонних страниц, встроенных в страницу. Одна страница отправляет сообщение, другая страница определяет источник и получает сообщение
// 发送消息端
var receiver = document.getElementById('receiver').contentWindow;
var btn = document.getElementById('send');
btn.addEventListener('click', function (e) {
e.preventDefault();
var val = document.getElementById('text').value;
receiver.postMessage("Hello "+val+"!", "http://res.42du.cn");
});
// 接收消息端
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event){
if (event.origin !== "http://www.42du.cn")
return;
}
Для получения подробной информации см.MDN | window.postMessage
Существуют также такие методы, как window.name и location.hash. Оба больше подходят для междоменных фреймов, но фреймы используются реже, поэтому эти методы немного устарели.
использованная литература
Подробное объяснение CORS для совместного использования ресурсов между доменами