尝试访问以编程方式创build的<iframe>的文档对象时,“访问被拒绝”JavaScript错误(仅限IE)

我有项目,我需要使用JavaScript创build一个<iframe>元素,并将其附加到DOM。 之后,我需要在<iframe>中插入一些内容。 这是一个embedded第三方网站的小部件。

我不设置<iframe>的“src”属性,因为我不想加载页面; 相反,它用于隔离/沙箱中插入的内容,以便不会遇到与父页面发生CSS或JavaScript冲突。 我使用JSONP从服务器加载一些HTML内容,并将其插入到<iframe>中。

我有这个工作正常,有一个严重的例外 – 如果document.domain属性设置在父页面(它可能在某些部署此小部件的环境中),Internet Explorer(可能是所有版本,但我确认在6,7和8)给我一个“访问被拒绝”的错误,当我尝试访问这个<iframe>我创build的文档对象。 在我testing过的任何其他浏览器(所有主要的现代浏览器)中都不会发生这种情况。

这是有道理的,因为我知道Internet Explorer要求您设置所有的窗口/框架将相互通信到相同的值document.domain。 但是,我不知道有什么方法可以在我无法访问的文档上设置此值。

有谁知道这样做的方式 – 以某种方式设置这个dynamic创build的<iframe>的document.domain属性? 或者,我没有从正确的angular度来看待这个问题吗?还有另外一种方法可以实现我要做的事情,而不会遇到这个问题吗? 在任何情况下,我确实需要使用<iframe>,因为隔离/沙盒窗口对于这个小部件的function至关重要。

这是我的testing代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Document.domain Test</title> <script type="text/javascript"> document.domain = 'onespot.com'; // set the page's document.domain </script> </head> <body> <p>This is a paragraph above the &lt;iframe&gt;.</p> <div id="placeholder"></div> <p>This is a paragraph below the &lt;iframe&gt;.</p> <script type="text/javascript"> var iframe = document.createElement('iframe'), doc; // create <iframe> element document.getElementById('placeholder').appendChild(iframe); // append <iframe> element to the placeholder element setTimeout(function() { // set a timeout to give browsers a chance to recognize the <iframe> doc = iframe.contentWindow || iframe.contentDocument; // get a handle on the <iframe> document alert(doc); if (doc.document) { // HEREIN LIES THE PROBLEM doc = doc.document; } doc.body.innerHTML = '<h1>Hello!</h1>'; // add an element }, 10); </script> </body> </html> 

我已经在:

http://troy.onespot.com/static/access_denied.html

正如你将看到,如果你在IE中加载这个页面,在我调用alert()的时候,我确实在<iframe>的窗口对象上有句柄。 我只是无法深入到它的文档对象中。

非常感谢您的帮助或build议! 我会感激任何人可以帮我find解决办法。

如果在父页面中设置document.domain属性,Internet Explorer会给我一个“访问被拒绝”

叹。 是的,这是一个IE问题(错误?很难说,因为没有这种不愉快的文件标准)。 当你创build一个无主文件的iframe时,它会从父文档的location.host而不是document.domain中接收一个document.domain 。 在这一点上,你几乎失去了,因为你不能改变它。

一个可怕的解决方法是将src设置为javascript:URL(urgh!):

  iframe.src= "javascript:'<html><body><p>Hello<\/p><script>do things;<\/script>'"; 

但由于某种原因,这样的文档无法从IE中的脚本设置自己的document.domain (好的旧“未指定的错误”),所以你不能用它来重新获得父(*)之间的桥梁。 您可以使用它来编写整个文档HTML,假设小部件在实例化后不需要与其父文档进行交谈。

然而iframe中的JavaScript URL在Safari中不起作用,所以你仍然需要某种浏览器嗅探来select使用哪种方法。

*:出于某种其他原因,您可以在IE中将document.domain从第二个文档设置为document.write由第一个文档创build。 所以这个工作:

 if (isIE) iframe.src= "javascript:'<script>window.onload=function(){document.write(\\'<script>document.domain=\\\""+document.domain+"\\\";<\\\\/script>\\');document.close();};<\/script>'"; 

在这一点上,可怕的程度对我来说太高了,我出去了。 我会像David说的那样做外部的HTML。

是的,访问exception是由于document.domain必须在你的父母和你的iframe中匹配,而在他们做之前,你将无法以编程方式设置你的iframe的document.domain属性。

我认为你最好的select是把页面指向你自己的模板:

 iframe.src = '/myiframe.htm#' + document.domain; 

而在myiframe.htm中:

 document.domain = location.hash.substring(1); 

以及我其实有一个非常类似的问题,但有一个转折…说顶级网站是a.foo.com – 现在我将文档域设置为a.foo.com

然后在我创build/拥有的iframe中,我也将其设置为a.foo.com

请注意,我不能将它们设置太foo.com B / C有指向bafoo.com(它再次使用a.foo.com页面中的另一个iframe,但我不能在那里更改脚本代码)

你会注意到,即时通讯本质上设置document.domain到它已经是反正…但我必须这样做,以访问我提到的其他iframe从bafoo.com

在我的框架内,我设置域后,尽pipe所有iframe具有相同的设置,我仍然遇到了一个错误,当在IE 6/7

还有其他的东西,真正bizaree

在外部/顶层,如果我等待它的onload事件,并设置一个计时器,最终我可以到达我需要访问的框架….但我永远不能从下往上达到…而我真的需要能够

如果我把所有东西都设置为foo.com(正如我所说我不能这么做) 但由于某种原因,当使用相同的价值location.host ….它没有和它的怪异杀死我…..

我只是使用<iframe src="about:blank" ...></iframe> ,它工作正常。

对IE来说,这个港口很重要。 在域之间,它应该是相同的端口。

你有没有试过jQuery.contents() ?

当你尝试通过document.frames对象访问iframe的时候,IE的问题似乎就出现了 – 如果你在一个variables中存储了对创build的iframe的引用,那么你可以通过variables访问注入的iframe(my_iframe在下面的代码中)。

我已经得到这个工作在IE6 / 7/8

 var my_iframe; var iframeId = "my_iframe_name" if (navigator.userAgent.indexOf('MSIE') !== -1) { // IE wants the name attribute of the iframe set my_iframe = document.createElement('<iframe name="' + iframeId + '">'); } else { my_iframe = document.createElement('iframe'); } iframe.setAttribute("src", "javascript:void(0);"); iframe.setAttribute("scrolling", "no"); iframe.setAttribute("frameBorder", "0"); iframe.setAttribute("name", iframeId); var is = iframe.style; is.border = is.width = is.height = "0px"; if (document.body) { document.body.appendChild(my_iframe); } else { document.appendChild(my_iframe); } 

我有一个类似的问题,我的解决scheme是这个代码片段(在IE8 / 9,Chrome和Firefox中testing)

 var iframe = document.createElement('iframe'); document.body.appendChild(iframe); iframe.src = 'javascript:void((function(){var script = document.createElement(\'script\');' + 'script.innerHTML = "(function() {' + 'document.open();document.domain=\'' + document.domain + '\';document.close();})();";' + 'document.write("<head>" + script.outerHTML + "</head><body></body>");})())'; iframe.contentWindow.document.write('<div>foo</div>'); 

我已经尝试了几种方法,但这个似乎是最好的。 你可以在我的博客文章中find一些解释。

遵循Andralor的非常简单的方法,在这里为我解决了这个问题: https : //github.com/fancyapps/fancyBox/issues/766

实质上,再次调用iframe onUpdate:

 $('a.js-fancybox-iframe').fancybox({ type: 'iframe', scrolling : 'visible', autoHeight: true, onUpdate: function(){ $("iframe.fancybox-iframe"); } }); 

IE浏览器像所有其他浏览器(至less主要function)与iframe一起工作。 你只需要遵守一套规则:

  • 在加载iframe中的任何javascript之前(需要了解iframe父级的那部分js),请确保父级已更改document.domain。
  • 当所有iframe资源加载时,将document.domain更改为与父项中定义的相同。 (您需要稍后执行此操作,因为设置域会导致iframe资源的请求失败)

  • 现在你可以为父窗口做一个引用:var winn = window.parent

  • 现在您可以对父HTML进行引用,以便操作它:var parentContent = $('html',winn.document)
  • 在这一点上,你应该有权访问IE的父窗口/文件,你可以改变它,因为你不会

对我来说,我发现最好的答案是检查访问被拒绝的文件权限。

我只是更新到jQuery-1.8.0.js并获得IE9中的访问拒绝错误。

从Windows资源pipe理器

  • 我右键单击文件select属性
  • select安全选项卡
  • 点击高级button
  • select所有者选项卡
  • 点击编辑button
  • 选定的pipe理员(MachineName \ Administrators)
  • 点击应用
  • closures所有的窗户。

testing该网站。 没有更多的问题。

我不得不为刚刚更新的jQuery-UI脚本做同样的事情