‹iframe› родителски DOM достъп до javascript в различни домейни?

Аз контролирам съдържанието на iframe, който е вграден в страница от друг домейн. Има ли някакъв начин javascript в моя iframe да прави промени в DOM на родителя?

Например, бих искал моят iframed скрипт да добави куп html елементи към родителския DOM. Това изглежда като доста трудна поръчка - мисли?

Редактиране: Съществува техника, наречена „Fragment ID Messaging“, която може да бъде начин за комуникация между iframe между домейни.

Редактиране: Освен това Firefox 3.5, Opera, Chrome (и т.н.) изглежда приемат html5 "postMessage" API, който позволява сигурно предаване на данни между домейни между рамки, вградени рамки и изскачащи прозорци. Работи като система за събития. Очевидно IE8 поддържа тази функция, което може би е малко изненадващо.

Резюме: Не, не можете директно да осъществявате достъп/редактирате DOM на страница от друг домейн. Но вие можете да общувате с него и той може да си сътрудничи, за да направи промените, които искате.


person aaaidan    schedule 18.08.2009    source източник
comment
Понастоящем приетият отговор беше правилен през 2009 г., но времената са се променили. Стефан Щайгер е по-добър и може би си струва да промените приетия си отговор към него.   -  person Quentin    schedule 08.06.2016
comment
Благодаря @Quentin, ще обмисля това.   -  person aaaidan    schedule 08.06.2016


Отговори (5)


Мразя да го кажа, но съм 99% сигурен, че това не се случва директно поради сигурността.

Можете да го изпробвате тук.

бхх

person Andy Gaskell    schedule 18.08.2009
comment
Благодаря, тази връзка показва проблема много добре. - person aaaidan; 18.08.2009
comment
Това, което можете да направите, е да имате iframe обратно към родителския домейн от дъщерния домейн и всички скриптове там да имат достъп до parent.parent, защото е в същия домейн, това се използва от няколко рекламни компании, които ще ви помолят да хоствате файл ( вътрешната iframe) на вашия сайт, за да им позволите да преоразмеряват добавките. - person Hayden Crocker; 26.11.2013
comment
Моля, прочетете отговора на @Stefan Steiger по-долу. Можете да комуникирате между фреймове с кръстосан произход, като използвате postMessage(). Разбира се, трябва да притежавате и двата домейна. - person Marco Panichi; 31.10.2017

Възможно е.

Имахте право да споменете postMessage във вашите редакции. За тези, които търсят, има страхотен обратно съвместим, само с javascript начин за комуникация между домейни. Също така кратък и лесен код. Идеалното решение? Докато можете да поискате модификации на родителя и детето:

http://www.onlineaspect.com/2010/01/15/backwards-compatible-postmessage/

person Kyle    schedule 23.11.2010

Да, можеш.
Можете да приложите window.postMessage за комуникация между iframes и/или прозорци между домейни.
Но трябва да го направите по асинхронен начин.
Ако имате нужда от него синхронно, трябва да внедрите обвивки около тези асинхронни методи.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title></title>

    <!--
    <link rel="shortcut icon" href="/bg/favicon.ico">


    <link rel="start" href="http://benalman.com/" title="Home">

    <link rel="stylesheet" type="text/css" href="/bg/code/php/multi_file.php?m=benalman_css">

    <script type="text/javascript" src="/js/mt.js"></script>
    -->
    <script type="text/javascript">
        // What browsers support the window.postMessage call now?
        // IE8 does not allow postMessage across windows/tabs
        // FF3+, IE8+, Chrome, Safari(5?), Opera10+

        function SendMessage()
        {
            var win = document.getElementById("ifrmChild").contentWindow;

            // http://robertnyman.com/2010/03/18/postmessage-in-html5-to-send-messages-between-windows-and-iframes/


            // http://stackoverflow.com/questions/16072902/dom-exception-12-for-window-postmessage
            // Specify origin. Should be a domain or a wildcard "*"

            if (win == null || !window['postMessage'])
                alert("oh crap");
            else
                win.postMessage("hello", "*");
            //alert("lol");
        }



        function ReceiveMessage(evt) {
            var message;
            //if (evt.origin !== "http://robertnyman.com")
            if (false) {
                message = 'You ("' + evt.origin + '") are not worthy';
            }
            else {
                message = 'I got "' + evt.data + '" from "' + evt.origin + '"';
            }

            var ta = document.getElementById("taRecvMessage");
            if (ta == null)
                alert(message);
            else
                document.getElementById("taRecvMessage").innerHTML = message;

            //evt.source.postMessage("thanks, got it ;)", event.origin);
        } // End Function ReceiveMessage




        if (!window['postMessage'])
            alert("oh crap");
        else {
            if (window.addEventListener) {
                //alert("standards-compliant");
                // For standards-compliant web browsers (ie9+)
                window.addEventListener("message", ReceiveMessage, false);
            }
            else {
                //alert("not standards-compliant (ie8)");
                window.attachEvent("onmessage", ReceiveMessage);
            }
        }
    </script>


</head>
<body>

    <iframe id="ifrmChild" src="child.htm" frameborder="0" width="500" height="200" ></iframe>
    <br />


    <input type="button" value="Test" onclick="SendMessage();" />

</body>
</html>

Дете.htm

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title></title>

    <!--
    <link rel="shortcut icon" href="/bg/favicon.ico">


    <link rel="start" href="http://benalman.com/" title="Home">

    <link rel="stylesheet" type="text/css" href="/bg/code/php/multi_file.php?m=benalman_css">

    <script type="text/javascript" src="/js/mt.js"></script>
    -->

    <script type="text/javascript">
        /*
        // Opera 9 supports document.postMessage() 
        // document is wrong
        window.addEventListener("message", function (e) {
            //document.getElementById("test").textContent = ;
            alert(
                e.domain + " said: " + e.data
                );
        }, false);
        */

        // https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage
        // http://ejohn.org/blog/cross-window-messaging/
        // http://benalman.com/projects/jquery-postmessage-plugin/
        // http://benalman.com/code/projects/jquery-postmessage/docs/files/jquery-ba-postmessage-js.html

        // .data – A string holding the message passed from the other window.
        // .domain (origin?) – The domain name of the window that sent the message.
        // .uri – The full URI for the window that sent the message.
        // .source – A reference to the window object of the window that sent the message.
        function ReceiveMessage(evt) {
            var message;
            //if (evt.origin !== "http://robertnyman.com")
            if(false)
            {
                message = 'You ("' + evt.origin + '") are not worthy';
            }
            else
            {
                message = 'I got "' + evt.data + '" from "' + evt.origin + '"';
            }

            //alert(evt.source.location.href)

            var ta = document.getElementById("taRecvMessage");
            if(ta == null)
                alert(message);
            else
                document.getElementById("taRecvMessage").innerHTML = message;

            // http://javascript.info/tutorial/cross-window-messaging-with-postmessage
            //evt.source.postMessage("thanks, got it", evt.origin);
            evt.source.postMessage("thanks, got it", "*");
        } // End Function ReceiveMessage




        if (!window['postMessage'])
            alert("oh crap");
        else {
            if (window.addEventListener) {
                //alert("standards-compliant");
                // For standards-compliant web browsers (ie9+)
                window.addEventListener("message", ReceiveMessage, false);
            }
            else {
                //alert("not standards-compliant (ie8)");
                window.attachEvent("onmessage", ReceiveMessage);
            }
        }
    </script>


</head>
<body style="background-color: gray;">
    <h1>Test</h1>

    <textarea id="taRecvMessage" rows="20" cols="20" ></textarea>

</body>
</html>

Тук бихте променили детето да изпраща пощенски съобщения до родител. напр. в child.htm, вие го правите

window.parent.postMessage("alert(document.location.href); document.location.href = 'http://www.google.com/ncr'", "*");

и в parent правите (в receiveMessage) eval(evt.data); Не че използването на eval е несигурно, така че вместо това бихте предали enum и извикали съответната функция, която трябва да поставите на родителската страница.

person Stefan Steiger    schedule 31.05.2013
comment
Зареждането на дъщерния iframe няма да работи в среда със смесен режим. Например главната страница в https и дъщерната страница в iframe (http). - person lmiguelmh; 02.03.2016
comment
@lmiguelmh: http страница не трябва да се зарежда в https страница на първо място. - person Stefan Steiger; 14.06.2018

Предполагам, че ще имате проблеми със сигурността, без да използвате прокси. Прокситата могат да бъдат много полезни. Можете да опитате едно от тези:

(1) базиран на PHP прокси (бъдете внимателни, защото има много реклами между полезни връзки)

(2) Apache .htaccess прокси - просто създайте поддиректория proxy във вашия домейн и поставете там .htaccess файл, съдържащ:

RewriteEngine on
RewriteRule ^(.*)$ http://picasaweb.google.com/$1 [P,L] 

Поставете другото име на домейн на мястото на picasaweb.google.com

Лично аз предпочитам да използвам Apache прокси

person warpech    schedule 19.08.2009
comment
Благодаря за отговора, warpech. Мисля, че моите редакции обаче объркаха първоначалния ми въпрос, който питаше как мога да променя dom на родителска страница от iframe от друг домейн. Краткият отговор изглежда е, че не можете. Така че сега проучвам методите за междукадрова комуникация и прокси сървърът със сигурност е един от тях. Благодаря! - person aaaidan; 20.08.2009

За AJAX сървърът може да върне заглавката Access-Control-Allow-Origin: *, за да позволи достъп между домейни. Може би работи и за IFRAME.

person user836773    schedule 10.07.2011