2009-12-11 7 views
73

Ich habe ein Projekt, in dem ich ein <iframe> -Element mit JavaScript erstellen und an das DOM anhängen muss . Danach muss ich etwas Inhalt in den <iframe> einfügen. Es ist ein Widget, das in Websites von Drittanbietern eingebettet wird."Zugriff verweigert" JavaScript-Fehler beim Versuch, auf das Dokumentobjekt eines programmgesteuerten <iframe> zuzugreifen (nur IE)

Ich setze nicht das "src" Attribut des <iframe>, da ich keine Seite laden möchte; Es wird vielmehr verwendet, um den Inhalt, den ich in den Inhalt einfüge, zu isolieren/sandboxieren, sodass ich keine CSS- oder JavaScript-Konflikte mit der übergeordneten Seite bekomme. Ich verwende JSONP, um einige HTML-Inhalte von einem Server zu laden und in diesen <iframe> einzufügen.

Ich habe dies funktioniert gut, mit einer ernsten Ausnahme - wenn die Eigenschaft document.domain in der übergeordneten Seite (die es in bestimmten Umgebungen sein kann, in denen dieses Widget bereitgestellt wird), Internet Explorer (wahrscheinlich alle Versionen, aber ich habe in 6, 7 und 8 bestätigt) gibt mir einen "Zugriff wird verweigert" Fehler, wenn ich versuche, auf das Dokumentobjekt dieses <iframe> zuzugreifen, das ich erstellt habe. Es passiert nicht in anderen Browsern, in denen ich getestet habe (alle wichtigen modernen).

Das macht einen Sinn, da ich weiß, dass Internet Explorer erfordert, dass Sie die document.domain aller Fenster/Frames, die miteinander kommunizieren, auf den gleichen Wert setzen. Mir ist jedoch keine Möglichkeit bekannt, diesen Wert für ein Dokument festzulegen, auf das ich nicht zugreifen kann.

Kennt jemand eine Möglichkeit, dies zu tun - irgendwie die Eigenschaft document.domain dieser dynamisch erstellten <iframe> setzen? Oder schaue ich es nicht aus dem richtigen Blickwinkel an - gibt es einen anderen Weg, um das zu erreichen, was ich will, ohne auf dieses Problem zu stoßen? Ich muss in jedem Fall einen <iframe> verwenden, da das isolierte/sandboxed-Fenster für die Funktionalität dieses Widgets entscheidend ist.

Hier ist mein Testcode:

<!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> 

Ich habe es bei gehosteten:

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

Wie Sie sehen, wenn Sie diese Seite in IE laden, an dem Punkt, dass ich Call Alert(), ich habe ein Handle auf das Fensterobjekt des <iframe>; Ich kann einfach nicht tiefer in sein Dokumentobjekt eindringen.

Vielen Dank für jede Hilfe oder Anregungen! Ich werde denen danken, die mir helfen können, eine Lösung dafür zu finden.

Antwort

62

wenn die document.domain Eigenschaft auf der Seite Mutter gesetzt ist, gibt mir den Internet Explorer ein

Sigh "Zugriff verweigert". Ja, es ist ein IE-Problem (Bug? Schwer zu sagen, da es keinen dokumentierten Standard für diese Art von Unannehmlichkeiten gibt). Wenn Sie einen srcless iframe erstellen, erhält er eine document.domain aus dem location.host des übergeordneten Dokuments statt seiner document.domain. An diesem Punkt haben Sie ziemlich verloren, da Sie es nicht ändern können.

Eine schreckliche Abhilfe ist src auf ein Javascript zu setzen: URL (urgh!):

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

Aber aus irgendeinem Grund, ein solches Dokument ist nicht in der Lage zu sein eigenes document.domain aus Skript in IE (gute alte gesetzt "Unspezifizierter Fehler"), so dass Sie das nicht verwenden können, um eine Brücke zwischen dem Eltern (*) wiederzugewinnen. Sie könnte verwenden, um das gesamte Dokument HTML zu schreiben, vorausgesetzt, das Widget muss nicht mit seinem übergeordneten Dokument sprechen, sobald es instanziiert ist.

Allerdings funktionieren iframe-JavaScript-URLs in Safari nicht. Sie benötigen also eine Art Browser-Sniffing, um die zu verwendende Methode auszuwählen.

*: Aus einem anderen Grund können Sie , in IE, document.domain aus einem zweiten Dokument, document.written vom ersten Dokument. So funktioniert das:

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

An diesem Punkt ist das Abscheulichkeitsniveau für mich zu hoch, ich bin draußen. Ich würde das externe HTML machen, wie David sagte.

+10

@bobince: Du bist großartig! Ich bin tatsächlich am späten Abend nach sehr viel mehr Googeln über diesen Ansatz gestolpert. Tatsächlich hätte ich vielleicht eine noch robustere und möglicherweise weniger kludrige Cross-Browser-Lösung gefunden: http://www.telerik.com/community/forums/aspnet-ajax/editor/document-domain-access-denied -in-ie-6.aspx - beachten Sie Jeff Tuckers Post vom 21. August. Setzen Sie das "src" -Attribut derauf "javascript: void ((function() {document.open(); document.domain = \ 'tld .com \ '; document.close();})()) "scheint den Trick zu machen, und in einer Browser-übergreifenden Weise. Es funktioniert auch in Safari (mindestens v3 +). – Bungle

+1

Hier ist eine Testseite, die meinen vorherigen Kommentar illustriert: http://troy.onespot.com/static/access_denied_test.html – Bungle

+1

Oh großartig! Das ist viel besser! Interessant, dass es direkt funktionieren sollte ... normalerweise würde eine javascript: URL im Kontext des übergeordneten Elements ausgeführt, aber das scheint bei iframe src nicht der Fall zu sein. Sie können wahrscheinlich auch den 'void()' Aufruf verlieren, da die Funktion bereits 'undefined' zurückgibt. – bobince

1

Haben Sie versucht jQuery.contents()?

+1

Deniss, guten Vorschlag, und danke - ich gab dies eine Chance (siehe ) aber einen ähnlichen Fehler bekommen; Diesmal ist es "Permission denied" innerhalb des jQuery-Skripts. Ich vermute, es ist die gleiche oder eine ähnliche Blockade. – Bungle

+1

Sorry, diese URL wurde beschädigt. Versuchen Sie es: http://troy.onespot.com/static/access_denied_jquery.html – Bungle

+4

Warum sollte jQuery magischen Zugriff auf das Dokument des iframes haben? –

18

Nun ja, die Zugriffsausnahme ist aufgrund der Tatsache, dass document.domain in Ihrem übergeordneten und Ihrem iframe übereinstimmen müssen, und bevor sie dies tun, können Sie die document.domain-Eigenschaft Ihres iframe nicht programmgesteuert festlegen.

Ich denke, die beste Wahl ist hier die Seite in eine Vorlage der eigenen Punkt:

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

Und in myiframe.htm:

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

Danke, David - ich schätze, dass es eine solide Empfehlung zu sein scheint, aber ich würde diesen Ansatz lieber nicht nehmen, es sei denn, es wäre ein letzter Ausweg. Wenn ich richtig verstehe, müsste die Vorlage in der gleichen Domäne wie die übergeordnete Seite leben (ist das richtig?), Und dies würde die Implementierung für unsere Kunden komplizieren. Idealerweise sollte die Implementierung so einfach sein, wie ein paar Zeilen JavaScript in den HTML-Code ihrer Seiten einzufügen. – Bungle

+1

Ja, die Lösung erfordert eine andere Datei in genau dieser Domäne. Ich fürchte, das ist das Beste, was ich mir vorstellen kann. –

+1

@Bungle: Ich denke, es ist deine einzige Option. –

1

Es scheint, dass das Problem mit IE kommt, wenn Sie versuchen und Zugriff auf den iframe über das Objekt document.frames - Wenn Sie einen Verweis auf den erstellten iframe in einer Variablen speichern, dann können Sie den injizierten iframe über die Variable (my_iframe im Code unten).

Ich habe das bekommen in IE6 arbeiten/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); 
} 
+1

Danke. Dies scheint das Problem für mich behoben zu haben. – vit

+1

seltsame Sache ist, das war das gleiche, was ich benutzte. funktionierte gut, jetzt plötzlich, ich halte ständig Zugriff verweigert Fehler – frostymarvelous

+0

In IE 11 scheint dies nicht zu funktionieren. –

-10

Für mich fand ich die bessere Antwort war die Dateizugriffsrechte zu überprüfen, die zu wird der Zugriff verweigert.

Ich nur auf jQuery-1.8.0.js aktualisieren und bekam den Fehler Zugriff verweigert in IE9.

Windows Explorer

  • ich rechts auf die Datei geklickt haben ausgewählt, um die Eigenschaften
  • die Registerkarte Sicherheit Ausgewählte
  • den Advanced-Button Clicked
  • Ausgewählte Eigentümer Tab
  • klickte auf Schaltfläche bearbeiten
  • Ausgewählte Administratoren (MachineName \ Administrators)
  • Clicked Bewerben
  • Alle Fenster geschlossen.

die Seite getestet. Kein Problem mehr. Ich hatte gerade aktualisiert und

+2

Ich denke, Sie lösen ein anderes Problem. –

+5

Das OP erstellt ein Widget eines Drittanbieters. Sie können nicht erwarten, dass jeder Besucher alle diese Schritte ausführt, um das Widget anzuzeigen. – Christophe

2

gut, ich habe tatsächlich ein sehr ähnliches Problem

Ich hatte das gleiche für die die jQuery-UI-Skript zu tun, aber mit einem Twist ... sagt, dass die Top-Level-Seite ist a.foo.com - jetzt

dann in der iframe a.foo.com, die i/eigene erstellen, i Dokument Domain gesetzt zu i gesetzt es auch a.foo.com

beachten sie, dass i set kippe sie zu foo.com b/c gibt es eine weitere iframe auf der Seite zu bafoo.com hingewiesen (was wiederum verwendet a.foo.com, aber ich kann den Skriptcode dort ändern)

youll beachten Sie, dass im Wesentlichen im, Einstellung document.domain zu dem, was es ohnehin schon wäre ... aber ich muss das tun die anderen Iframe zuzugreifen i von bafoo.com erwähnt

in meinem Rahmen, nach ich habe die Domain, obwohl alle iframes die gleiche Einstellung haben, habe ich noch einen Fehler, wenn sie in die Mutter in IE 6/7

erreichen bis es gibt andere Dinge, die bizaree

in außen/oben wirklich r level, wenn ich auf sein onload-ereignis warte, und einen timer setze, kann ich schließlich in den rahmen greifen, auf den ich zugreifen muss .... aber ich kann nie von bot erreichen tom up ... und ich muss wirklich in der Lage zu

auch wenn ich alles auf foo.com gesetzt (was wie ich sagte, ich kann nicht tun) IT funktioniert! aber aus irgendeinem Grund, wenn Sie den gleichen Wert wie location.host verwenden .... es tutnt und seine Freaking tötet mich .....

2

Ich verwende einfach <iframe src="about:blank" ...></iframe> und es funktioniert gut.

2

für IE, die Port-Angelegenheiten. Dazwischen sollte es der gleiche Port sein.

1

hatte ich ein ähnliches Problem und meine Lösung war diesen Code-Schnipsel (in IE8 getestet/9, Chrome und Firefox)

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>'); 

Ich habe mehrere Methoden ausprobiert, aber dies schien das Beste zu sein. Sie können einige Erklärungen in meinem Blogpost here finden.

+0

Funktioniert nicht im IE11-Kompatibilitätsmodus – Suncatcher

1

die überaus einfache Methode von Andralor hier fixiert Nach dem Thema für mich: https://github.com/fancyapps/fancyBox/issues/766

Wesentlichen wieder die iframe onUpdate, rufen:

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

IE mit iframe funktioniert wie alle anderen Browsern (zumindest für Hauptfunktionen). Sie müssen nur eine Reihe von Regeln halten:

  • , bevor Sie eine Javascript in iframe laden (das Teil von js, die über die iframe Eltern wissen muss), stellen Sie sicher, dass die Eltern sich geändert hat document.domain.
  • wenn alle iframe Ressourcen geladen werden, ändern document.domain das gleiche wie die in Mutter definiert sein.(Sie müssen dies später tun, weil Domain Einstellung wird der iframe Ressource Anforderung fehlschlagen)

  • jetzt eine Referenz für übergeordnete Fenster machen kann: var winn = window.parent

  • jetzt können Sie einen Verweis machen Mutter HTML, es zu manipulieren, um: var parentContent = $ (‚html‘, winn.document)
  • an dieser Stelle haben Sie Zugriff auf IE übergeordnete Fenster/Dokument haben sollte, und Sie können es, wie Sie
  • ändern wont
Verwandte Themen