855 Stimmen

Sicherheitsfehler: Blockierte einen Rahmen mit Ursprung daran, auf einen Frame mit Ursprung von unterschiedlichen Ursprung zuzugreifen.

Ich lade ein </code> in meiner HTML-Seite und versuche, die Elemente darin mit JavaScript zu bearbeiten, aber wenn ich meinen Code ausführen möchte, erhalte ich den folgenden Fehler:</p> <blockquote> <p>Sicherheitsfehler: Ein Frame mit der Herkunft "http://www.example.com" wurde daran gehindert, auf einen Frame mit einer anderen Herkunft zuzugreifen.</p> </blockquote> <p>Wie kann ich auf die Elemente im Frame zugreifen?</p> <p>Ich verwende diesen Code zum Testen, aber vergeblich:</p> <pre class="lang-js prettyprint-override"><code>$(document).ready(function() { var iframeWindow = document.getElementById("my-iframe-id").contentWindow; iframeWindow.addEventListener("load", function() { var doc = iframe.contentDocument || iframe.contentWindow.document; var target = doc.getElementById("my-target-id"); target.innerHTML = "Gefunden!"; }); }); </code></pre></x-turndown>

1191voto

Marco Bonelli Punkte 55783

Same-origin policy

Sie können nicht auf ein </code> mit einer anderen Herkunft über JavaScript zugreifen, es wäre ein großer Sicherheitsfehler, wenn dies möglich wäre. Für die <a href="https://developer.mozilla.org/de/docs/Web/Security/Same-origin_policy" rel="noreferrer">Same-Origin-Richtlinie</a> blockieren Browser Skripte, die versuchen, auf ein Frame mit einer anderen Herkunft zuzugreifen.</p> <p>Eine Herkunft gilt als unterschiedlich, wenn mindestens einer der folgenden Teile der Adresse nicht übereinstimmt:</p> <pre><b>Protokoll</b>://<b>Hostname</b>:<b>Port</b>/...</pre> <p>Protokoll, Hostname und Port müssen die gleichen wie Ihre Domäne sein, wenn Sie auf ein Frame zugreifen möchten.</p> <p><sup>HINWEIS: Obwohl heutzutage größtenteils nicht mehr verwendet, ist bekannt, dass der Internet Explorer diese Regel nicht streng einhält, siehe <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Exceptions_in_Internet_Explorer" rel="noreferrer">hier</a> für Details.</sup></p> <h3>Beispiele</h3> <p>Hier ist, was passieren würde, wenn Sie versuchen würden, auf die folgenden URLs von <code>http://www.example.com/home/index.html</code> zuzugreifen:</p> <pre class="lang-none prettyprint-override"><code>URL ERGEBNIS http://www.example.com/home/other.html -> Erfolg http://www.example.com/dir/inner/another.php -> Erfolg http://www.example.com:80 -> Erfolg (Standardport für HTTP) http://www.example.com:2251 -> Fehler: Unterschiedlicher Port http://data.example.com/dir/other.html -> Fehler: Unterschiedlicher Hostname https://www.example.com/home/index.html:80 -> Fehler: Unterschiedliches Protokoll ftp://www.example.com:21 -> Fehler: Unterschiedliches Protokoll & Port https://google.com/search?q=james+bond -> Fehler: Unterschiedliches Protokoll, Port & Hostname </code></pre> <h2>Umgehungslösung</h2> <p>Auch wenn die Same-Origin-Richtlinie Skripte daran hindert, auf den Inhalt von Websites mit einer anderen Herkunft zuzugreifen, <strong>wenn Sie beide Seiten besitzen, können Sie dieses Problem umgehen, indem Sie <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage" rel="noreferrer"><code>window.postMessage</code></a> und das zugehörige <code>message</code> Ereignis verwenden</strong>, um Nachrichten zwischen den beiden Seiten zu senden, wie folgt:</p> <ul> <li><p>In Ihrer Hauptseite:</p> <pre><code>const frame = document.getElementById('Ihre-Frame-ID'); frame.contentWindow.postMessage(/* beliebige Variable oder Objekt hier */, 'https://Ihre-Zweite-Seite.example'); </code></pre> <p>Das zweite Argument für <code>postMessage()</code> kann <code>'*'</code> sein, um keine Präferenz hinsichtlich der Herkunft des Ziels anzugeben. Wenn möglich, sollte immer eine Zielherkunft angegeben werden, um zu vermeiden, dass die Daten, die Sie senden, an eine andere Website weitergegeben werden.</p> </li> <li><p>In Ihrem <code><iframe></code> (enthalten in der Hauptseite):</p> <pre><code>window.addEventListener('message', event => { // WICHTIG: Überprüfen Sie die Herkunft der Daten! if (event.origin === 'https://Ihre-Erste-Seite.example') { // Die Daten wurden von Ihrer Seite gesendet. // Die mit postMessage gesendeten Daten werden in event.data gespeichert: console.log(event.data); } else { // Die Daten wurden NICHT von Ihrer Seite gesendet! // Seien Sie vorsichtig! Verwenden Sie sie nicht. Dieser else-Zweig dient lediglich der Klarheit, normalerweise sollte er nicht benötigt werden. return; } }); </code></pre> </li> </ul> <p>Diese Methode kann in <strong>beiden Richtungen</strong> angewendet werden, indem auch in der Hauptseite ein Listener erstellt wird und Antworten vom Frame empfangen werden. Die gleiche Logik kann auch in Pop-ups und praktisch jedem von der Hauptseite generierten neuen Fenster (z.B. unter Verwendung von <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/open" rel="noreferrer"><code>window.open()</code></a>) implementiert werden, ohne Unterschiede.</p> <h2>Deaktivierung der Same-Origin-Richtlinie in <em>Ihrem</em> Browser</h2> <p>Es gibt bereits einige gute Antworten zu diesem Thema (ich habe sie gerade beim Googeln gefunden), daher werde ich für die Browser, in denen dies möglich ist, die entsprechende Antwort verlinken. Bitte bedenken Sie jedoch, dass <strong>das Deaktivieren der Same-Origin-Richtlinie nur <em>Ihren</em> Browser betrifft</strong>. Außerdem gewährt das Ausführen eines Browsers mit deaktivierten Same-Origin-Sicherheitseinstellungen <em>jeder</em> Website Zugriff auf ressourcenübergreifende Ressourcen, daher <strong>ist dies sehr unsicher und sollte NIE gemacht werden, wenn Sie nicht genau wissen, was Sie tun (z.B. für Entwicklungszwecke)</strong>.</p> <ul> <li><a href="https://stackoverflow.com/q/3102819/3889449">Google Chrome</a></li> <li><a href="https://stackoverflow.com/q/17088609/3889449">Mozilla Firefox</a></li> <li><a href="https://stackoverflow.com/q/4556429/3889449">Safari</a></li> <li><a href="https://stackoverflow.com/q/7543678/3889449">Opera</a>: gleich wie Chrome</li> <li>Microsoft Edge: gleich wie Chrome</li> <li>Brave: gleich wie Chrome</li> <li>Microsoft Edge (alte nicht-Chromium-Version): <a href="https://superuser.com/q/1020612/591004">nicht möglich</a></li> <li><a href="https://stackoverflow.com/q/20947359/3889449">Microsoft Internet Explorer</a></li> </ul></x-turndown>

71voto

Geert Punkte 3085

Als Ergänzung zu Marcos Bonellis Antwort: Derzeit ist der beste Weg, um zwischen Frames / IFrames zu interagieren, die Verwendung von window.postMessage, von allen Browsern unterstützt

29voto

Shahar Shokrani Punkte 6014

Überprüfen Sie den Webserver der Domain http://www.example.com auf die Konfiguration von X-Frame-Options Es handelt sich um ein Sicherheitsmerkmal, das entwickelt wurde, um Clickjacking-Angriffe zu verhindern.

Wie funktioniert Clickjacking?

  1. Die betrügerische Seite sieht genau wie die Opferseite aus.
  2. Dann werden die Benutzer getäuscht, ihre Benutzername und Passwort einzugeben.

Technisch gesehen hat die böswillige Seite ein iframe mit der Quelle zur Opferseite.

    <input id="username" type="text" style="display: none;"/>
    <input id="password" type="text" style="display: none;"/>
    <script>
        //Einige JS-Code, der den Benutzernamen und die Eingabe des Benutzers von innerhalb des iframes clickjackt...
    <script/>
<html>
</code></pre>
<h2>Wie funktioniert das Sicherheitsmerkmal?</h2>
<p>Wenn Sie möchten, dass Webserver-Anfragen nicht innerhalb eines <code>iframe</code> gerendert werden, fügen Sie das <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options" rel="nofollow noreferrer">x-frame-options</a> hinzu</p>
<blockquote>
<p>X-Frame-Options DENY</p>
</blockquote>
<p>Die Optionen sind:</p>
<ol>
<li><code>SAMEORIGIN</code>: erlauben Sie nur meiner eigenen Domain, mein HTML innerhalb eines iframes zu rendern.</li>
<li><code>DENY</code>: erlauben Sie nicht, dass mein HTML innerhalb eines iframes gerendert wird</li>
<li><code>ALLOW-FROM https://example.com/</code>: erlauben Sie einer spezifischen Domain, mein HTML innerhalb eines iframes zu rendern</li>
</ol>
<p>Dies ist ein Beispiel für die IIS-Konfiguration:</p>
<pre><code>   <httpProtocol>
       <customHeaders>
           <add name="X-Frame-Options" value="SAMEORIGIN" />
       </customHeaders>
   </httpProtocol>
</code></pre>
<h2>Die Lösung für die Frage</h2>
<p>Wenn der Webserver das Sicherheitsmerkmal aktiviert hat, kann dies einen SecurityError auf der Clientseite verursachen, wie es soll.</p></x-turndown>

20voto

Yakir Manor Punkte 4509

Für mich wollte ich einen 2-Wege-Handshake implementieren, das bedeutet:
- das übergeordnete Fenster wird schneller geladen als das iFrame
- das iFrame sollte sofort mit dem übergeordneten Fenster sprechen, sobald es bereit ist
- das übergeordnete Fenster ist bereit, die iFrame-Nachricht zu empfangen und zu antworten

dieser Code wird verwendet, um das White-Label im iFrame mit [CSS-Benutzerdefinierte Eigenschaft] festzulegen
code:
iFrame

$(function() {
    window.onload = function() {
        // Listener erstellen
        function receiveMessage(e) {
            document.documentElement.style.setProperty('--header_bg', e.data.wl.header_bg);
            document.documentElement.style.setProperty('--header_text', e.data.wl.header_text);
            document.documentElement.style.setProperty('--button_bg', e.data.wl.button_bg);
            //alert(e.data.data.header_bg);
        }
        window.addEventListener('message', receiveMessage);
        // Eltern aufrufen
        parent.postMessage("GetWhiteLabel","*");
    }
});

Eltern

$(function() {
    // Listener erstellen
    var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
    var eventer = window[eventMethod];
    var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
    eventer(messageEvent, function (e) {
        // An das Kind (iFrame) zurückschreiben
        document.getElementById('wrapper-iframe').contentWindow.postMessage(
            {
                event_id: 'white_label_message',
                wl: {
                    header_bg: $('#Header').css('background-color'),
                    header_text: $('#Header .HoverMenu a').css('color'),
                    button_bg: $('#Header .HoverMenu a').css('background-color')
                }
            },
            '*'
        );
    }, false);
});

natürlich können Sie die Ursprünge und den Text begrenzen, dies ist ein leicht zu bearbeitender Code
ich fand dieses Beispiel hilfreich:
[Cross-Domain Messaging Mit postMessage]

4voto

nikk wong Punkte 7239

Es gibt tatsächlich einen Workaround für spezifische Szenarien.

Wenn Sie zwei Prozesse auf demselben Domain, aber unterschiedlichen Ports laufen haben, können die zwei Windows ohne Einschränkungen interagieren. (z.B. localhost:3000 & localhost:2000). Um dies zum Funktionieren zu bringen, muss jedes Fenster seine Domain auf den gemeinsamen Ursprung ändern:

document.domain = 'localhost'

Dies funktioniert auch im Szenario, dass Sie mit verschiedenen Subdomains auf demselben zweiten Domain arbeiten, d.h. Sie sind auf john.site.example und versuchen auf peter.site.example oder einfach site.example zuzugreifen

document.domain = 'site.example'

Indem Sie document.domain explizit setzen; wird der Browser den Hostnamenunterschied ignorieren und die Windows können als aus derselben Ursprung kommend behandelt werden. Jetzt können Sie in einem Elternfenster auf das iframe zugreifen: frame.contentWindow.document.body.classList.add('happyDev')

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X