Политика того же происхождения
Вы не можете получить доступ к <iframe>
другому источнику, используя JavaScript, это было бы огромным недостатком безопасности, если бы вы могли это сделать. Для браузеров с политикой одного источника блокируют сценарии, пытаясь получить доступ к кадру с другим источником .
Источник считается другим, если хотя бы одна из следующих частей адреса не поддерживается:
<protocol>://<hostname>:<port>/...
Протокол , имя хоста и порт должны совпадать с вашим доменом, если вы хотите получить доступ к фрейму.
ПРИМЕЧАНИЕ. Известно, что Internet Explorer строго не следует этому правилу, подробности см. Здесь .
Примеры
Вот что произойдет при попытке получить доступ к следующим URL-адресам из http://www.example.com/home/index.html
URL RESULT
http://www.example.com/home/other.html -> Success
http://www.example.com/dir/inner/another.php -> Success
http://www.example.com:80 -> Success (default port for HTTP)
http://www.example.com:2251 -> Failure: different port
http://data.example.com/dir/other.html -> Failure: different hostname
https://www.example.com/home/index.html:80 -> Failure: different protocol
ftp://www.example.com:21 -> Failure: different protocol & port
https://google.com/search?q=james+bond -> Failure: different protocol, port & hostname
Временное решение
Несмотря на то, что политика одного и того же источника блокирует доступ сценариев к содержимому сайтов с другим источником, если вы владеете обеими страницами, вы можете обойти эту проблему, используя window.postMessage
ее относительное message
событие для отправки сообщений между двумя страницами, например:
На вашей главной странице:
let frame = document.getElementById('your-frame-id');
frame.contentWindow.postMessage(/*any variable or object here*/, 'http://your-second-site.com');
Вторым аргументом postMessage()
может быть '*'
указание на отсутствие предпочтений относительно источника назначения. По возможности всегда следует указывать целевое происхождение, чтобы избежать разглашения данных, которые вы отправляете на любой другой сайт.
В вашем <iframe>
(содержится на главной странице):
window.addEventListener('message', event => {
// IMPORTANT: check the origin of the data!
if (event.origin.startsWith('http://your-first-site.com')) {
// The data was sent from your site.
// Data sent with postMessage is stored in event.data:
console.log(event.data);
} else {
// The data was NOT sent from your site!
// Be careful! Do not use it. This else branch is
// here just for clarity, you usually shouldn't need it.
return;
}
});
Этот метод можно применять в обоих направлениях , создавая слушателя на главной странице и получая ответы из фрейма. Та же логика также может быть реализована во всплывающих окнах и в основном в любом новом окне, сгенерированном главной страницей (например, с помощью window.open()
), без каких-либо различий.
Отключение политики того же происхождения в вашем браузере
На эту тему уже есть несколько хороших ответов (я только что нашел их в поиске), поэтому для браузеров, где это возможно, я приведу относительный ответ. Однако помните, что отключение политики одного источника повлияет только на ваш браузер . Кроме того, запуск браузера с отключенными настройками безопасности того же источника предоставляет любому веб-сайту доступ к ресурсам из разных источников, поэтому это очень небезопасно и НИКОГДА не следует делать, если вы точно не знаете, что делаете (например, в целях разработки) .
Access-Control-Allow-Origin
не применяется к iFrames, только к XHR, Fonts, WebGL иcanvas.drawImage
. Я считаю,postMessage
что это единственный вариант.iframe.src
, и если сайт отличается от имени хоста вашего домена, вы не сможете получить доступ к этому фрейму.~
возвращает 2-е дополнение числа, такn
становится-n-1
, то есть становится , что только-1
станет0
(что интерпретируется какfalse
), и любое другое значение пройдет тест. То есть0 = -(-1)-1
, нет-(-1+1)
.location.ancestorOrigins[0]
- расположение родительского фрейма. Если ваш фрейм работает на другом сайте, и вы проверяете с помощью него,event.origin.indexOf(location.ancestorOrigins[0])
вы проверяете, содержит ли источник события адрес фрейма родителя, который всегда будетtrue
, поэтому вы разрешаете любому родителю с любым источником доступа к вашему фрейму, и это это явно не то, что вы хотите сделать. Более того,document.referrer
это тоже плохая практика, как я уже объяснял в комментариях выше.Ответ Дополняя Марко ястребиный: лучший способ ток взаимодействия между кадрами / фреймов используется
window.postMessage
, поддерживается всеми браузерамиисточник
window.postMessage
работает, только дублирует принятый ответ, на который я уже ссылаюсь. Более того, существенная ценность, которую добавляет мой ответ, заключается именно в ссылке на внешнюю документацию.Проверьте
http://www.<domain>.com
конфигурацию веб-сервера домена.X-Frame-Options
Это функция безопасности, предназначенная для предотвращения атак clickJacking,Как работает ClickJacking?
Технически зло связано
iframe
с источником на странице жертвы.Как работает функция безопасности
Если вы хотите, чтобы запрос веб-сервера не отображался в
iframe
добавлении, x-frame-optionsВарианты:
Это пример конфигурации IIS:
Решение вопроса
Если веб-сервер активировал функцию безопасности, это может вызвать клиентскую ошибку SecurityError, как и должно быть.
источник
Для меня я хотел реализовать двухстороннее рукопожатие, что означает:
- родительское окно будет загружаться быстрее, чем iframe
- iframe должно общаться с родительским окном, как только оно будет готово
- родитель готов получить сообщение iframe и воспроизвести его
этот код используется для установки белой метки в iframe с помощью кода [CSS custom property]
:
iframe
родитель
естественно, вы можете ограничить происхождение и текст, это простой в работе код, который
я нашел полезным для этого примера: [ междоменный обмен
сообщениями с postMessage]
источник
Я хотел бы добавить конкретную конфигурацию Java Spring, которая может повлиять на это.
В веб-сайте или приложении шлюза есть параметр contentSecurityPolicy
весной вы можете найти реализацию подкласса WebSecurityConfigurerAdapter
...
Браузер будет заблокирован, если вы не определили здесь безопасный внешний контент.
источник
Если у вас есть контроль над содержимым iframe, т. Е. Если он просто загружен в настройках с несколькими источниками, например в Amazon Mechanical Turk, вы можете обойти эту проблему с помощью
<body onload='my_func(my_arg)'>
атрибута для внутреннего html.Например, для внутреннего html используйте
this
параметр html (yes -this
определен и относится к родительскому окну внутреннего элемента body):<body onload='changeForm(this)'>
Во внутреннем html:
источник
chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security
источник