Изменение URL родительского окна из IFrame

У меня есть ситуация, когда у меня есть веб-приложения на двух разных серверах, где App1 содержит App2 в IFrame. Любые ссылки в App2 могут иметь атрибут target="_parent", который позволяет этим ссылкам открываться в верхнем окне. Тем не менее, я не могу найти способ получить такое же поведение в Javascript. Я нашел эту страницу, в которой утверждается, что дочерний фрейм может вызывать javascript в родительском фрейме с помощью parent.foo(), но это не похоже на работать в IE8 или FF3.5. Я нашел этот вопрос SO, в котором объясняется, как работает эта модель безопасности. Но кажется странным, что я не могу сделать в Javascript то, что я могу сделать с простым тегом <a>. Есть ли какое-либо обходное решение для этого? Я знаю о window.postMessage, но (насколько я знаю ) это работает только в Firefox.


Пример

server1/test.html

<html>
<head>
<script type="text/javascript">
function myCallback(foo) {
  alert(foo);
}
</script>
</head>
<body>
<iframe src="http://server2/test2.htm" width="400" height="150"></iframe>
</body></html>

server2/test2.html

<html><body>
<script>
function clickit() {
  parent.document.location = "http://www.google.com"; //not allowed
  parent.myCallback("http://www.google.com"); //not allowed
}
</script>
<p>This should be in an iFrame!</p>
<p><a href="#" onclick="location.href='http://www.google.com'; return false;" target="_parent">normal link (works)</a></p>
<p><a href="javascript:clickit()">javascript link</a></p>
</body></html>

Ответы

Ответ 1

ОК. Я сделал больше исследований, и кажется, что postMessage работает во всех современных браузерах, даже IE (с предостережением, что IE имеет несколько другой способ сделать это). Вот как я получил его на работу (протестирован на WinXP в IE8, FF3.5, Chrome 3.0, Safari 4 beta, Opera 9.64):

server1/test.html

<html>
<head>
<script type="text/javascript">
if(navigator.appName == "Microsoft Internet Explorer")
  window.attachEvent("onmessage", receiveMessage);
else
  window.addEventListener("message", receiveMessage, false);

function receiveMessage(e) {
  if(e.origin == "http://server2") //important for security
    if(e.data.indexOf('redirect:') == 0)
      document.location = e.data.substr(9);
}
</script>
</head>
<body>
<iframe src="http://server2/test2.htm" width="400" height="150"></iframe>
</body>
</html>

server2/Test2.htm

<html><body>
<script>
function clickit() {
  parent.postMessage('redirect:http://www.google.com', 'http://server1');
}
</script>
<p>This should be in an iFrame!</p>
<p><a href="http://www.google.com" target="_parent">normal link</a></p>
<p><a href="javascript:clickit()">javascript link</a></p>
</body></html>

Ответ 2

Простая вещь, которую вы можете сделать, это: выполнить следующее из кода JavaScript на странице iframe

top.location = "https://www.google.co.in/";

это изменит расположение URL-адреса окна на https://www.google.co.in/.

Еще одна вещь. Эта стратегия также может быть полезна, когда вы не хотите, чтобы кто-то мог переместить ваш сайт просто напишите вышеуказанный код в готовой части документа.

Ответ 3

Нет, и не зря. Если вам это нужно, вы должны запустить все коммуникации через один из двух серверов; например, сервер1 действует как прокси для всех запросов для "server2/test2.html".

Ответ 4

Если оба родителя и iframe находятся на поддоменах в одном домене, вы можете что-то сделать с помощью свойства document.domain. Если оба тела и iframe рассматриваются как имеющие одно и то же происхождение, изменение местоположения должно быть возможным; Я сам этого не пробовал. Некоторое чтение здесь

Ответ 5

Если кадры находятся в одном домене, вы должны иметь доступ к родительскому фрейму. В противном случае это проблема безопасности.

Единственное временное решение, которое приходит на ум, - использовать AJAX для обновления файла на каждом из серверов, а затем проверить содержимое противоположной файловой серверной части. Вы можете сделать то же самое, используя единую базу данных, если вы разрешаете подключения из внешних доменов.

Это все-таки избыток, хотя вы можете просто выставить ссылку в фрейме и сообщить пользователям, чтобы он нажал его, чтобы продолжить.