Можно сказать, что "междоменная" проблема является одной из наиболее часто встречающихся проблем в веб-разработке. Хотя она относительно проста, ее также относительно легко решить. Но из этого вопроса можно многое узнать. Вот подробное резюме.
что такое кросс домен
Из соображений безопасности браузеры делают много вещей, одна из которых — политика того же происхождения.
Политика одинакового происхождения/SOP (политика единого происхождения) – это соглашение, которое было введено в браузеры компанией Netscape в 1995 году. Это основная и самая основная функция безопасности браузеров. Без единой политики происхождения браузеры уязвимы для XSS. , CSFR и другие атаки. Так называемая гомология означает, что «протокол + доменное имя + порт» одинаковы, даже если два разных доменных имени указывают на один и тот же IP-адрес, они не гомологичны.
Политика того же происхождения ограничивает следующие действия:
- Файлы cookie, LocalStorage и IndexDB не могут быть прочитаны
- Объекты DOM и Js не могут быть получены
- Запрос AJAX не может быть отправлен
Это также вводит ряд междоменных проблем.Следует отметить, что:
Междоменный не означает, что браузер ограничивает инициирование межсайтовых запросов, но что межсайтовые запросы могут инициироваться нормально, но возвращаемый результат перехватывается браузером. Лучшим примером является принцип межсайтовой атаки CSRF, запрос отправляется на внутренний сервер независимо от того, является ли он междоменным или нет! Примечание. Некоторые браузеры не разрешают междоменный доступ к HTTP из доменов HTTPS, например Chrome и Firefox. Эти браузеры блокируют запросы до их отправки. Это особый случай.
Зачем нужен междоменный
Политика одинакового происхождения AJAX в основном используется для предотвращения атак CSRF. Если нет AJAX-политики того же происхождения, это довольно опасно, каждый HTTP-запрос, который мы инициируем, будет приносить cookie, соответствующий адресу запроса, поэтому могут быть выполнены следующие атаки:
1. Пользователь входит на страницу своего банка http://mybank.com, и http://mybank.com добавляет идентификатор пользователя в файл cookie пользователя.
2. Пользователь просматривает вредоносную страницу http://evil.com. Выполняется вредоносный код запроса AJAX на странице.
3. http://evil.com инициирует HTTP-запрос AJAX к http://mybank.com, и запрос по умолчанию отправляет соответствующий файл cookie на http://mybank.com.
4. Страница банка извлекает идентификатор пользователя из отправленного файла cookie, проверяет правильность пользователя и возвращает данные запроса в ответ. В этот момент происходит утечка данных.
5. А поскольку Ajax выполняется в фоновом режиме, пользователь не может воспринимать этот процесс.
То же самое относится и к политике одинакового происхождения DOM: если к iframe можно получить доступ из разных доменов, их можно атаковать следующим образом:
1. Создайте поддельный веб-сайт с веб-сайтом банка http://mybank.com, вложенным в iframe.
2. Настройте ширину и высоту iframe на всю страницу, чтобы пользователи заходили кроме имени домена, а остальные части ничем не отличались от сайта банка.
3. В это время, если пользователь вводит пароль учетной записи, наш основной веб-сайт может получить доступ к узлу dom http://mybank.com через домен, и ввод пользователя может быть получен, после чего атака завершена. Следовательно, с междоменными и междоменными ограничениями мы можем более безопасно путешествовать по Интернету.
междоменное решение
В реальной разработке из-за бизнес-проблем наши приложения могут быть распределены по разным доменным именам или портам, и мы столкнемся с ограничением политики одного и того же происхождения.Существуют следующие решения для решения этой проблемы.
jsonp
принцип
Хотя имяjsonp
, на самом деле его принцип не имеет ничего общего с json. в основном с использованием теговsrc
Атрибуты не подпадают под политику того же происхождения для получения данных из других доменов. Обычно мы используем теги img/script. Наиболее часто используется тег script. Поскольку js выполняет функции других доменов сам по себе и путем передачи параметров функциям, цель междоменного взаимодействия может быть достигнута.
Как использовать
Сначала мы сначала определяем функцию.
function callback(data){
console.log(data);
}
Затем введите файл js из другого домена, например:Лян Сичэн Oh.com/Run_call положил C…, в этом файле вызовcallback
функции и передать параметры, мы получаем данные из других доменов.
callback({title:'jsonp演示'});
Приведенный выше код был вставлен на страницу этой статьи, откройте консоль, чтобы увидеть данные
Используя это, мы можем передавать произвольные параметры этой функции. Итак, мы можем вернуться к фонуcallback(+任意数据+)
для достижения междоменных целей.
Потому что jquery оборачивает jsonp следующим образом.
$.ajax({
method: 'jsonp',
url: 'http://example2.com',
success: function(data) {
console.log(data)
}
})
Многие думают, что jsonp — это что-то связанное с ajax, но это не так. Ajax использует XMLHTTPRequest для запроса данных, и на него распространяются ограничения на одно и то же происхождение. Просто jquery оборачивает описанный выше процесс для согласованности API.
jsonp также имеет много недостатков, таких как поддержка только запросов на получение и не может передавать данные в обоих направлениях.
window.name
принцип
Параметр имени в объекте окна может быть разделен между несколькими окнами (вкладками), используя это, мы можем передавать данные. В сочетании с iframe у вас могут быть более мощные функции. Например, откройте iframe и установите адрес вне домена, установите его во внешнем домене.window.name
, а затем вернуться к этому домену, в это время вы также можете получить настройки чужого доменаwindow.name
, в настоящее время цель междоменного взаимодействия достигнута. Размер передаваемых данных обычно составляет 2 МБ, а в браузерах IE и Firefox может достигать 32 МБ, а формат данных можно настроить.
Как использовать
//a.html
<script type="text/javascript">
var state = 0,
iframe = document.createElement('iframe'),
loadfn = function() {
if (state === 1) {
var data = iframe.contentWindow.name; // 读取数据
alert(data); //弹出'I was there!'
} else if (state === 0) {
state = 1;
iframe.contentWindow.location = "http://a.com/proxy.html"; // 设置的代理文件
}
};
iframe.src = 'http://b.com/b.html';
if (iframe.attachEvent) {
iframe.attachEvent('onload', loadfn);
} else {
iframe.onload = loadfn;
}
document.body.appendChild(iframe);
</script>
//proxy.html
//空文件放在a.com下起中转作用即可
//b.html
<script type="text/javascript">
window.name = 'I was there!'; // 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右,数据格式可以自定义,如json、字符串
</script>
Недостаток в том, что это более хлопотно, и для этого нужно создать iframe, который легко перехватывается браузером xx.
document.domain
принцип
принцип иwindow.name
Аналогично, при взаимодействии разных поддоменов + iframe не проблема получить объект окна другого iframe, но нельзя использовать большинство методов и свойств полученного окна. Это явление можно решить с помощью document.domain.
Как использовать
//a.com
<iframe id='i' src="b.com" onload="do()"></iframe>
<script>
document.domain = 'a.com';
document.getElementById("i").contentWindow;
</script>
//b.com
<script>
document.domain = 'a.com';
</script>
Таким образом, проблема может быть решена. Стоит отметить, что настройка document.domain ограничена и может быть установлена только на саму страницу или доменное имя более высокого уровня.
Это более удобно в использовании, но если один веб-сайт будет атакован, другой веб-сайт, скорее всего, создаст дыры в безопасности.
location.hash
принцип
Этот метод может отображать изменения данных в хеше URL-адреса. Но поскольку хром и IE не позволяют изменять значение parent.location.hash, необходимо добавить еще один слой.
Как использовать
Пример: a.html и b.html для обмена данными.
//a.html
function startRequest(){
var ifr = document.createElement('iframe');
ifr.style.display = 'none';
ifr.src = 'http://2.com/b.html#paramdo';
document.body.appendChild(ifr);
}
function checkHash() {
try {
var data = location.hash ? location.hash.substring(1) : '';
if (console.log) {
console.log('Now the data is '+data);
}
} catch(e) {};
}
setInterval(checkHash, 2000);
//b.html
//模拟一个简单的参数处理操作
switch(location.hash){
case '#paramdo':
callBack();
break;
case '#paramset':
//do something……
break;
}
function callBack(){
try {
parent.location.hash = 'somedata';
} catch (e) {
// ie、chrome的安全机制无法修改parent.location.hash,
// 所以要利用一个中间域下的代理iframe
var ifrproxy = document.createElement('iframe');
ifrproxy.style.display = 'none';
ifrproxy.src = 'http://3.com/c.html#somedata'; // 注意该文件在"a.com"域下
document.body.appendChild(ifrproxy);
}
}
//c.html
//因为parent.parent和自身属于同一个域,所以可以改变其location.hash的值
parent.parent.location.hash = self.location.hash.substring(1);
Таким образом, взаимодействие между a и b может быть достигнуто путем хеширования с использованием промежуточного слоя c.
window.postMessage()
принцип
Этот метод является новой функцией HTML5 и может использоваться для отправки сообщений всем другим оконным объектам. Следует отметить, что мы должны убедиться, что все скрипты выполнены перед отправкой MessageEvent, Если он вызывается во время выполнения функции, он делает последующую функцию тайм-аутом и не может быть выполнен.
CORS
Именно этому посвящено сегодняшнее введение, это чуть ли не самое совершенное решение на данный момент. Это также наиболее используемая программа.
принцип
Полное название CORS — Cross-Origin Resource Sharing, то есть совместное использование ресурсов между источниками. Его принцип заключается в использовании специального HTTP-заголовка, позволяющего серверу взаимодействовать с браузером, в основном путем установки Access-Control-Allow-Origin заголовка ответа для достижения цели. Таким образом, XMLHttpRequest может быть междоменным. является стандартом W3C.
Как использовать
установить заголовки ответа
имя поля | Это необязательно | иллюстрировать |
---|---|---|
Access-Control-Allow-Origin | требуется | Указывает источник запроса, разрешенный сервером, * определяет любой внешний домен, несколько источников, разделенных |
Access-Control-Allow-Credentials | необязательный | Это поле является необязательным. Его значение является логическим значением, указывающим, разрешать ли отправку файлов cookie. По умолчанию файлы cookie не включаются в запросы CORS. Установите значение true (и withCredentials в запросе ajax должно быть установлено значение true), что означает, что сервер явно разрешил включить cookie в запрос и отправить его на сервер вместе. Это значение может быть установлено только в true.Если сервер не хочет, чтобы браузер отправлял файлы cookie, просто удалите это поле. |
Access-Control-Expose-Headers | необязательный | Параметры, которые можно получить из заголовка при вызове метода getResponseHeader() |
Может быть, мы подумаем, что политика одного и того же источника ограничена браузером. Какой смысл устанавливать заголовок ответа? На данный момент браузер еще не отправил запрос. Чтобы реализовать этот стандарт, браузеры делят запросы CORS на простые запросы и не очень простые запросы. Простой запрос — это прямой запрос, вместо простого запроса сначала будет отправлен сниффинг-запрос типа options, а последующий обычный запрос будет сделан только после того, как будет пройден ответ и проверка.
простой запрос
(1) 请求方法是以下三种方法之一:HEAD、GET、POST (2)HTTP的头信息不超出以下几种字段: Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
Для простых запросов браузер делает запросы CORS напрямую. В частности, к информации заголовка добавляется поле Origin. Поле Origin используется для указания источника (протокол + доменное имя + порт), из которого исходит этот запрос. На основе этого значения сервер решает, соглашаться ли на запрос.
Если источник, указанный Origin, не входит в разрешенную область, сервер вернет обычный HTTP-ответ. Браузер обнаруживает, что информация заголовка этого ответа не содержит поля Access-Control-Allow-Origin (подробности см. ниже), и знает, что произошла ошибка, поэтому выдает ошибку, которая перехватывается функцией обратного вызова onerror. XMLHttpRequest. Обратите внимание, что этот тип ошибки не может быть идентифицирован по коду состояния, поскольку код состояния ответа HTTP может быть 200.
Если доменное имя, указанное Origin, находится в допустимом диапазоне, ответ, возвращаемый сервером, будет содержать несколько дополнительных полей заголовка. Оба начинаются с Access-Control-.
Мы используем axios для имитации запроса. Здесь используются сервисы интерфейса, предоставляемые cnodejs. благодарный.
axios.get('https://cnodejs.org/api/v1/topics');
Если мы откроем консоль, мы обнаружим, что хотя запрос является междоменным, прямой запрос выполнен успешно. Просто потому, что запрос является простым запросом, посмотрите на заголовок запроса и заголовок ответа.
не простой запрос
Любой запрос, который не удовлетворяет условиям простого запроса, считается непростым запросом. Для непростых запросов запрос HTTP-запроса, называемый «предварительным» запросом, добавляется перед формальным общением. Тип - варианты.
Браузер сначала запрашивает у сервера, находится ли доменное имя текущей страницы в списке разрешенных сервером и какие HTTP-команды и поля заголовка можно использовать. Браузер выдаст формальный запрос XMLHttpRequest только в случае положительного ответа, в противном случае он сообщит об ошибке.
Мы моделируем запрос
axios.put('https://cnodejs.org/api/v1/topics');
Видно, что есть два запроса, первый запрос типа optios, в основном для определения того, разрешен ли запрос, если разрешен, следующий запрос будет продолжен.
axios.put('https://baidu.com');
Давайте снова выполним этот код, и мы обнаружим, что он только один.options
тип запроса, и консоль выдает исключение. Причина в том, что сервер не разрешает междоменные запросы. браузер через этоoptions
тип запроса, получить заголовки ответа и создать исключение.
С другой стороны, старые браузеры не реализуют стандарт, поэтому не поддерживают его. Из-за сложного механизма перехвата запросов это увеличит нагрузку на сервер.
В сравнении
Сравнив вышесказанное, мы обнаружим, что CORS не только прост в использовании, поддерживает все типы запросов, имеет контроль разрешений и изначально поддерживается браузером, мы можем легко обрабатывать исключения запросов. Полезно для устранения неполадок. Поэтому в большинстве случаев мы предпочтем этот метод. В браузерах более ранних версий jsonp можно использовать с другими методами для обеспечения совместимости.
Эта статья написана lscho создавать, использоватьАтрибуция Creative Commons 4.0Международное лицензионное соглашение о лицензировании
Статьи на этом сайте являются оригинальными или переведены этим сайтом, если не указана перепечатка/источник, обязательно подпишитесь перед перепечаткой
Последнее редактирование: 05 05, 2018