Способы обойти политику того же происхождения
Та же политика происхождения
Я хотел создать вики сообщества для политик HTML/JS с тем же происхождением, чтобы, надеюсь, помочь всем, кто ищет эту тему. Это одна из самых популярных тем на SO, и нет консолидированной вики для нее, так что я пойду:)
Такая же политика происхождения не позволяет документу или скрипту, загруженному из одного источника, получать или задавать свойства документа из другого источника. Эта политика восходит к Netscape Navigator 2.0.
Каковы ваши любимые способы обхода политики одного и того же происхождения?
Пожалуйста, сохраняйте подробные примеры и, желательно, делайте ссылки на свои источники.
11 ответов
document.domain
метод
- Тип метода: iframe.
Обратите внимание, что это метод iframe, который устанавливает значение document.domain в суффикс текущего домена. Если это так, более короткий домен используется для последующих проверок происхождения. Например, предположим, что скрипт в документе http://store.company.com/dir/other.html
выполняет следующее утверждение:
document.domain = "company.com";
После выполнения этого оператора страница пройдет проверку источника с http://company.com/dir/page.html
, Однако по той же причине, company.com не может установить document.domain
в othercompany.com
,
С помощью этого метода вам будет разрешено извлекать javascript из iframe, созданного на поддомене, на странице, созданной в основном домене. Этот метод не подходит для междоменных ресурсов, так как браузеры, такие как Firefox, не позволят вам изменить document.domain
в полностью чужой домен.
Источник: https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript
Метод совместного использования ресурсов из разных источников
- Тип метода: AJAX.
Обмен ресурсами между источниками (CORS) - это рабочий проект W3C, который определяет, как браузер и сервер должны взаимодействовать при доступе к источникам из разных источников. Основная идея CORS состоит в том, чтобы использовать пользовательские заголовки HTTP, чтобы браузер и сервер знали достаточно друг о друге, чтобы определить, будет ли запрос или ответ успешным или нет.
Для простого запроса, который использует либо GET
или же POST
без пользовательских заголовков и чье тело text/plain
запрос отправляется с дополнительным заголовком Origin
, Заголовок Origin содержит источник (протокол, имя домена и порт) запрашивающей страницы, так что сервер может легко определить, должен ли он обслуживать ответ. Пример Origin
заголовок может выглядеть так:
Origin: http://www.stackru.com
Если сервер решает, что запрос должен быть разрешен, он отправляет Access-Control-Allow-Origin
заголовок, возвращающий тот же источник, который был отправлен или *
если это публичный ресурс. Например:
Access-Control-Allow-Origin: http://www.stackru.com
Если этот заголовок отсутствует или источники не совпадают, браузер отклоняет запрос. Если все хорошо, то браузер обрабатывает запрос. Обратите внимание, что ни запросы, ни ответы не содержат информацию о файлах cookie.
Команда Mozilla в своем сообщении о CORS предлагает проверить наличие withCredentials
свойство, чтобы определить, поддерживает ли браузер CORS через XHR. Затем вы можете соединиться с существованием XDomainRequest
Объект для покрытия всех браузеров:
function createCORSRequest(method, url){
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr){
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined"){
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
xhr = null;
}
return xhr;
}
var request = createCORSRequest("get", "http://www.stackru.com/");
if (request){
request.onload = function() {
// ...
};
request.onreadystatechange = handler;
request.send();
}
Обратите внимание, что для работы метода CORS вам необходим доступ к механике заголовков сервера любого типа, и вы не можете просто получить доступ к сторонним ресурсам.
Источник: http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
window.postMessage
метод
- Тип метода: iframe.
window.postMessage
при вызове вызывает MessageEvent
отправляется в целевое окно, когда любой ожидающий сценарий, который должен быть выполнен, завершается (например, оставшиеся обработчики событий, если window.postMessage
вызывается из обработчика событий, предварительно установленных таймаутов ожидания и т. д.). MessageEvent
имеет сообщение типа, data
свойство, которое устанавливается в строковое значение первого аргумента, предоставленного window.postMessage
, origin
свойство, соответствующее происхождению основного документа в окне вызова window.postMessage
в это время window.postMessage
был назван, и source
свойство, которое является окном, из которого window.postMessage
называется.
Использовать window.postMessage
слушатель события должен быть прикреплен:
// Internet Explorer
window.attachEvent('onmessage',receiveMessage);
// Opera/Mozilla/Webkit
window.addEventListener("message", receiveMessage, false);
И receiveMessage
Функция должна быть объявлена:
function receiveMessage(event)
{
// do something with event.data;
}
Внешнее iframe также должно правильно отправлять события через postMessage
:
<script>window.parent.postMessage('foo','*')</script>
Любое окно может получить доступ к этому методу в любом другом окне, в любое время, независимо от местоположения документа в окне, чтобы отправить ему сообщение. Следовательно, любой прослушиватель событий, используемый для получения сообщений, должен сначала проверить личность отправителя сообщения, используя свойства источника и, возможно, источника. Это не может быть преуменьшено: неспособность проверить origin
и, возможно, source
Свойства позволяют атаковать межсайтовый скриптинг.
Источник: https://developer.mozilla.org/en/DOM/window.postMessage
Метод обратного прокси
- Тип метода: Ajax
Установка простого обратного прокси на сервере позволит браузеру использовать относительные пути для запросов Ajax, в то время как сервер будет действовать как прокси для любого удаленного местоположения.
При использовании mod_proxy в Apache основная директива конфигурации для настройки обратного прокси - это ProxyPass
, Обычно используется следующим образом:
ProxyPass /ajax/ http://other-domain.com/ajax/
В этом случае браузер сможет запросить /ajax/web_service.xml
как относительный URL, но сервер будет служить этому, выступая в качестве прокси для http://other-domain.com/ajax/web_service.xml
,
Одна интересная особенность этого метода заключается в том, что обратный прокси-сервер может легко распределять запросы по нескольким серверам, тем самым выступая в качестве балансировщика нагрузки.
Я использую JSONP.
В основном, вы добавляете
<script src="http://..../someData.js?callback=some_func"/>
на твоей странице.
some_func () должен быть вызван так, чтобы вы были уведомлены, что данные находятся в.
AnyOrigin плохо работал с некоторыми сайтами https, поэтому я просто написал альтернативу с открытым исходным кодом http://whateverorigin.org/, которая, кажется, хорошо работает с https.
Я не могу претендовать на кредит за это изображение, но оно соответствует всему, что я знаю по этому вопросу, и в то же время предлагает немного юмора.
Самый последний способ преодоления политики, основанной на происхождении, который я нашел, - это http://anyorigin.com/
Сайт сделан так, что вы просто даете ему любой URL, и он генерирует для вас код javascript/jquery, который позволяет вам получать html / data, независимо от его происхождения. Другими словами, он делает любой URL или веб-страницу запросом JSONP.
Я нашел это довольно полезным:)
Вот несколько примеров кода javascript из anyorigin:
$.getJSON('http://anyorigin.com/get?url=google.com&callback=?', function(data){
$('#output').html(data.contents);
});
На ум приходит JSONP:
JSONP или "JSON with padding" является дополнением к базовому формату данных JSON, шаблону использования, который позволяет странице запрашивать и более осмысленно использовать JSON с сервера, отличного от основного сервера. JSONP - это альтернатива более позднему методу, который называется Cross-Origin Resource Sharing.
Этот анализ в значительной степени анализирует то, что доступно там: http://www.slideshare.net/SlexAxton/breaking-the-cross-domain-barrier
Для решения postMessage взгляните на:
https://github.com/chrissrogers/jquery-postmessage/blob/master/jquery.ba-postmessage.js
и немного другая версия:
https://github.com/thomassturm/ender-postmessage/blob/master/ender-postmessage.js
Вот некоторые обходные пути и объяснение политики того же происхождения:
Thiru's Blog - Обходной путь политики браузера того же происхождения
Ну, я использовал curl в PHP, чтобы обойти это. У меня есть веб-сервис, работающий в порту 82.
<?php
$curl = curl_init();
$timeout = 30;
$ret = "";
$url="http://localhost:82/put_val?val=".$_GET["val"];
curl_setopt ($curl, CURLOPT_URL, $url);
curl_setopt ($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($curl, CURLOPT_MAXREDIRS, 20);
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5");
curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
$text = curl_exec($curl);
echo $text;
?>
Вот JavaScript, который делает вызов файла PHP
function getdata(obj1, obj2) {
var xmlhttp;
if (window.XMLHttpRequest)
xmlhttp=new XMLHttpRequest();
else
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","phpURLFile.php?eqp="+obj1+"&val="+obj2,true);
xmlhttp.send();
}
Мой HTML работает на WAMP в порту 80. Итак, мы обошли ту же политику происхождения:-)
Лично, window.postMessage
это самый надежный способ, который я нашел для современных браузеров. Вы должны сделать немного больше работы, чтобы убедиться, что вы не оставляете себя открытым для атак XSS, но это разумный компромисс.
Есть также несколько плагинов для популярных инструментариев Javascript, которые обертывают window.postMessage
которые предоставляют аналогичную функциональность для старых браузеров, используя другие методы, описанные выше.