Javascript 从 IFrame 更改父窗口的 URL

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1860470/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 21:39:40  来源:igfitidea点击:

Changing parent window's URL from IFrame

javascripthtmlsecurityiframe

提问by Kip

I have a situation where I have web apps on two different servers, where App1 contains App2 in an IFrame. Any links in App2 can have target="_parent"attribute, which allow those links to open in the top window. However, I can't find any way to get the same behavior in Javascript. I found this page, which claimsthat the child frame can call javascript on the parent frame using parent.foo(), but that doesn't seem to work in IE8 or FF3.5. I found this SO questionwhich explains how this security model works. But it seems odd that I can't do in Javascript what I can do with a simple <a>tag. Is there any workaround to this at all?I know about window.postMessage, but (as far as I know) this only works in Firefox.

我有一种情况,我在两个不同的服务器上都有 Web 应用程序,其中 App1 在 IFrame 中包含 App2。App2 中的任何链接都可以有target="_parent"属性,允许这些链接在顶部窗口中打开。但是,我找不到在 Javascript 中获得相同行为的任何方法。我找到了这个页面,它声称子框架可以使用 调用父框架上的 javascript parent.foo(),但这在 IE8 或 FF3.5 中似乎不起作用。我发现这个 SO question解释了这个安全模型是如何工作的。但是我不能用 Javascript 做我可以用一个简单的<a>标签做的事情,这似乎很奇怪。 有什么解决方法吗?我知道window.postMessage,但是(据我所知)这只适用于 Firefox。



Example

例子

server1/test.html

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

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="http://www.google.com" target="_parent">normal link (works)</a></p>
<p><a href="javascript:clickit()">javascript link</a></p>
</body></html>

采纳答案by Kip

OK I did more investigation, and it appears that postMessage works in all modern browsers, even IE (with the caveat that IE has a slightly different way of doing it). Here's how I got it to work (tested on WinXP in IE8, FF3.5, Chrome 3.0, Safari 4 beta, Opera 9.64):

好吧,我做了更多调查,看来 postMessage 可以在所有现代浏览器中使用,甚至是 IE(但需要注意的是 IE 的处理方式略有不同)。这是我如何让它工作(在 IE8、FF3.5、Chrome 3.0、Safari 4 beta、Opera 9.64 中的 WinXP 上测试):

server1/test.html

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

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>

回答by Nirbhay Mishra

A simple thing you can do is: execute following from JavaScript code of iframe page

您可以做的一件简单的事情是:从 iframe 页面的 JavaScript 代码执行以下操作

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

this will change the location of window's URL to https://www.google.co.in/.

这会将窗口 URL 的位置更改为https://www.google.co.in/.

One more thing -This strategy can also be useful when you do not want that any one can inframe your site just write the above code in document ready part.

另一件事 - 当您不希望任何人可以将您的站点装入框架时,此策略也很有用,只需在文档准备部分编写上述代码即可。

回答by Aaron Digulla

No, and for good reason. If you need this, then you must run all communication through one of the two servers; for example, have server1 act as as a proxy for all requests for "server2/test2.html".

不,而且有充分的理由。如果您需要这个,那么您必须通过两台服务器之一运行所有通信;例如,让 server1 作为对“server2/test2.html”的所有请求的代理。

回答by Pekka

If both parent and iframe are on subdomains under the same domain, you maybe able to do something with the document.domainproperty. If both body and iframe are treated as being from the same origin, changing the location should be possible; I haven't tried this myself. Some reading here

如果 parent 和 iframe 都在同一个域下的子域上,则您可以对该document.domain属性执行某些操作。如果将 body 和 iframe 视为来自同一来源,则应该可以更改位置;我自己没试过这个。一些阅读在这里

回答by DisgruntledGoat

If the frames are on the same domain, you should be able to access the parent frame. Otherwise no, it's a security issue.

如果框架在同一个域中,您应该能够访问父框架。否则不,这是一个安全问题。

The only workaround that springs to mind would be to use AJAX to update a file on each of the servers, then check the contents of the opposite file server-side. You could do the same thing using a single database, if you allow connections from external domains.

唯一想到的解决方法是使用 AJAX 更新每个服务器上的文件,然后检查相反文件服务器端的内容。如果您允许来自外部域的连接,您可以使用单个数据库执行相同的操作。

This is all kind of overkill though, when you could simply pop-up a link in the frame and tell users to click it to continue.

但是,这有点矫枉过正,因为您可以简单地在框架中弹出一个链接并告诉用户单击它以继续。