7

JavaScript のクロス ドメイン セキュリティの問題を解決するために、次のメソッドを実装しています。

ドメイン [ abc.com ]

ドメインabc.comに というページがありますmain_page.html。そのコードは次のとおりです -

<script>
function SendMsg(id)
{
   frames["invisible_iframe"].location = "http://xyz.com/invisible_iframe.html#"+id;
}
</script>
<body>
  <input type="button" id="Test" value="Call iFrame" onclick="SendMsg(this.id);">
  <iframe src="ttp://xyz.com/visible_iframe.html" name="visible_iframe" height="250" width="500"></iframe>
  <iframe name="invisible_iframe" height="0" width="0" style="display:none;"></iframe>
</body>

ドメイン [ xyz.com ]

ドメインxyz.comに というページがありますvisible_iframe.html。そのコードは次のとおりです -

<script>
function Hi()
{
   alert("Hi there!");
}
</script>
<body>
  <h1>Visible iFrame on xyz.com
  <iframe name="d2_invisible_iframe" id="d2_invisible_iframe" class="iFrame" src="http://xyz.com/invisible_iframe.html" height="310" width="520"></iframe>
</body>

今、私は(同じドメイン上にある)Hi()から関数にアクセスしたいinvisible_iframe.html

のコードinvisible_iframe.htmlは次のとおりです

<script>
var sActionText = "";
function CheckForMessages()
{
   if(location.hash != sActionText)
   {
     sActionText = location.hash;
     var sAction = "";
     var oSplitActionText = sActionText.split("#");
     sAction = oSplitActionText[1];
     if (sAction == "Test")
     {
        parent.Hi();
     }
   }
}

setInterval(CheckForMessages, 200); 
</script>
<body>
  <h1>Invisible iFrame on xyz.com</h1>
</body>

visible_iframe.htmlvisible_iframe.html の URL を変更したくないため、非表示の iFrame を使用しています。

ボタンをmain_page.htmlクリックすると、アラートメッセージが表示されると思います。しかし、そうはなりません。Firefoxでは、プロパティ「こんにちは」へのアクセスが拒否されました

parent.Hi();奇妙なことに、関数の外に置くCheckForMessages()と、Hi()関数にアクセスでき、警告ボックスが表示されます。

これを解決するにはどうすればよいですか?

4

9 に答える 9

4

なぜeasyXDMを使用しないのですか? このライブラリは、あなたの人生を本当に楽にし、クロスドメインの問題に対処する際のセキュリティ制限を回避するのに役立ちます. 特に、2 つのドメインを制御できる場合。

easyXDM は、開発者が Same Origin Policy によって設定された制限を簡単に回避できるようにする Javascript ライブラリです。これにより、ドメインの境界を越えて JavaScript API の通信と公開が容易になります。

[これは、最も優れた使いやすい API の 1 つです] Web アプリケーション間のクロス ドメイン通信に使用できます。easyXDM は使いやすく、軽量で、柔軟性があり、高品質のコードを記述できます。クロスドメイン シナリオを継続する場合は、easyXDM などの堅牢なクロスドメイン API を採用する必要があると強く思います。

[easyXDM vs PostMessage Transport?] easyXDM は、この機能が (IE8+、Opera 9+、Firefox 3+、Safari 4+、Chrome 2+) などのブラウザーで有効になっている場合、反対側で PostMessageTransport メソッドを使用します。サポートされていないブラウザー (Firefox 1-2 - FrameElementTransport を使用) などのトランスポート メソッドは、必要に応じて FlashTransport、NameTransport、HashTransport などの他のトランスポート メソッドが使用されます。

これにより、ブラウザのサポート、特に古いブラウザの点で、easyXDM が明らかに優れています。


easyXDM (ドメイン 1 [abc.com] がリモート ドメイン [xyz.com] のメソッドを呼び出す) を使用したクロスドメイン アクセスを示すには:


*ドメイン [ abc.com ] - メイン ドメイン*

    <script type="text/javascript">
        /**
         * Request the use of the JSON object
         */
        easyXDM.DomHelper.requiresJSON("../json2.js");
    </script>
    <script type="text/javascript">
        var remote;
        window.onload = function(){
            /**
             * When the window is finished loading start setting up the interface
             */
            remote = new easyXDM.Interface(/** The channel configuration */{
                /**
                 * Register the url to hash.html, this must be an absolute path
                 * or a path relative to the root.
                 * @field
                 */
                local: "/hash.html",
                /**
                 * Register the url to the remote interface
                 * @field
                 */
                remote: "http://YOUR.OTHER.DOMAIN/YOUR_APPLICATION/YourRemoteApplication.html",
                /**
                 * Register the DOMElement that the generated IFrame should be inserted into
                 */
                container: document.getElementById("embedded")
            }, /** The interface configuration */ {
                remote: {
                    remoteApplicationMethod: {},
                    noOp: {
                        isVoid: true
                    }
                },
                local: {
                    alertMessage: {
                        method: function(msg){
                            alert(msg);
                        },
                        isVoid: true
                    }
                }
            },/**The onReady handler*/ function(){
                /**
                 * Call a method on the other side
                 */
                remote.noOp();
            });
        }

        function callRemoteApplicationMethod(Value1, Value2){
            remote.remoteApplicationMethod(Value1, Value2, function(result){
                alert("Results from remote application" + result);
            });
        }


    </script>

体内で

<input type="button" onclick="callRemoteApplicationMethod(3,5)" value="call remoteApplicationMethod on remote domain"/>

リモート ドメイン側で、次のようにリモート クライアントを定義する必要があります。

*ドメイン [ xyz.com ] - リモート ドメイン*

これは、ページ YOUR_APPLICATION/YourRemoteApplication.html に移動する必要があります。

    <script type="text/javascript">
        /**
         * Request the use of the JSON object
         */
        easyXDM.DomHelper.requiresJSON("../json2.js");
    </script>
    <script type="text/javascript">
        var channel, remote;
        /**
         * When the window is finished loading start setting up the channel
         */
        window.onload = function(){

            /**
             * When the channel is ready we create the interface
             */
            remote = new easyXDM.Interface(/** The channel configuration*/{}, /** The configuration */ {
                remote: {
                    alertMessage: {
                        isVoid: true
                    }
                },
                local: {
                    remoteApplicationMethod: {
                        method: doSomething(value1, value2){
                        // do somethigs with values

                        return "i'm return value from remote domain";
                        }
                    },
                    noOp: {
                        isVoid: true,
                        method: function(){
                            alert("Method not returning any data");
                        }
                    }
                }
            });
        }
    </script>
于 2012-06-09T21:53:09.440 に答える
3

古いブラウザをサポートする必要はないと思いますよね?最新のブラウザーでwindow.postMessageを使用して、クロスオリジン通信をサポートできます。

于 2012-06-12T07:11:54.720 に答える
2

あなたは原因を信じないでしょう。main_page.html (abc.com) で 2 つの iframe を定義しますが、それらを閉じません (</iframe> がありません)。現在、次の 2 つのケースがあります。

ケース 1:

iframe は独立しているため、main_page.html コードは

<iframe src="http://xyz.com/visible_iframe.html" ...></iframe>
<iframe src="http://xyz.com/invisible_iframe.html" ...></iframe>

invisible_iframe.html からの JavaScript 呼び出しは、

parent.frames["visible_iframe"].Hi();

ケース 2:

iframe は親子であるため、main_page.html コードは

<iframe src="http://xyz.com/visible_iframe.html" ...></iframe>

visible_iframe.html コードを含める必要があります

<iframe src="http://xyz.com/invisible_iframe.html" ...></iframe>

invisible_iframe.html からの JavaScript 呼び出しは、

parent.Hi();

それで全部です。選択はあなた次第です。

于 2012-06-10T21:37:57.983 に答える
0

iframeを削除して、ライブラリでjsonpを使用すると思います。1.クロスドメインエラーなし2.データをオブジェクトとして取得できます('emで簡単に操作できます3.uが解析できるJSコードを取得することもできます。4。モバイル対応でも可能です(iframeは前世紀のソリューションです。 。)しかし、何らかの理由でiframeを削除できない可能性があるため、既製のライブラリソリューションを使用することをお勧めします。Goodluck

于 2012-06-16T08:26:10.153 に答える
0

あなたの入力であなたの作品を仮定するとonlcick(ちょうどそこにタイプミスがありますinvisible_frame):visible_frameHi()parent.frames['visible_frame'].Hi()

今のところ、はのページ (フレームのであるため)parent.Hi()にアクセスしようとするため、Same Origin Policy のハード スティックで突かれます。Hi()abc.comparent

これが役に立ち、うまくいくことを願っています;)

于 2012-06-07T09:52:31.907 に答える
0

代替手段、プロキシ。

サーバー側で外部ファイルを取得し、エコー バックします。今はあなたのドメインにあるので問題ありません。

たとえばphp

<?php
  $external-site = file_get_contents('http://xyz.com/');
  echo $external-site;
?>
于 2012-06-15T02:13:18.497 に答える
0

CORS (Cross-Origin Resource Sharing)またはwindow.postMessage(参照: MDN のドキュメントまたは別の単純な postMessage の例) は、IE7 のサポートを気にしない場合は、調査する価値があります。postMessage古い IE ブラウザーに shim を使用することもできます。

ただし、あなたの質問により正確に答えるために、iframe ソリューションに固執します。

parent残念ながら、クロス ドメイン iframe から(windowスコープ) プロパティ/メソッドにアクセスすることはできません。windowただし、同じドメインの iframe を介してスコープにアクセスできます...任意の深さで。したがって、1 つの解決策は、垂直 iframe トンネルを活用することです。

3 つの HTML ドキュメントを作成する場合:

トップレベル - abc.com

<script>
    function sendMsg( id ) {
       frames["invisible_iframe"].location = "//xyz.com/mid_level.html#" + id;
    }

    window.ACTIONS = {
        Test: function() {
            alert("hello");
            // This action could also start an interaction with another
            // visible iframe by setting a hash, etc
        }
    };
</script>
<input type="button" id="Test" value="Call iFrame" onclick="sendMsg(this.id);">
<iframe name="invisible_iframe" height="0" width="0" frameborder="0" style="visibility:hidden;" src="//xyz.com/mid_level.html"></iframe>

中級レベル - xyz.com

<script>
    function sendMsg( id ) {
       frames["invisible_iframe"].location = "//abc.com/low_level.html#" + id;
    }

    var sActionText = "";
    function checkForMessages() {
       if(location.hash != sActionText) {
         sActionText = location.hash.replace(/^#/, "");
         location.hash = "";

         sendMsg(sActionText);
       }
    }

    setInterval(checkForMessages, 20); 
</script>
<iframe name="invisible_iframe" height="0" width="0" frameborder="0" style="visibility:hidden;" src="//abc.com/low_level.html"></iframe>

低レベル - abc.com

<script>
    function runActionInTop( action ) {
        try {
            window.top.ACTIONS[action]();
        } catch ( err ) {
            // Bad action!
        }
    }

    var sActionText = "";
    function checkForMessages() {
       if(location.hash != sActionText) {
         sActionText = location.hash.replace(/^#/, "");
         location.hash = "";

         runActionInTop(sActionText);
       }
    }

    setInterval(checkForMessages, 20); 
</script>

これら 3 つの iframe は通信できます。1 番目と 3 番目は直接通信でき、2 番目は間接的に (この例ではハッシュを介して) 通信できます。

これは、「目に見える iframe」で最初に表示しようとしていたものとは異なります。クロスサイト通信に必要なレイヤリングを説明することに集中したかったのです。それでも可視の iframe が必要な場合は、最上位に通信フックを追加し、追加情報を (ハッシュで) 中央のフレームから最下位のフレームに送り返すことができます (最下位のフレームは、情報を直接最上位に通信することができます)。ページ)。

はい、私はこれが複雑であることを知っています-それがCORSと存在する理由の1つですpostMessage:)

また、指摘する価値があると思われる元のコードのいくつかの小さな側面を変更しました。

  • //の代わりに使用http://すると、このシステムは http または https で動作します。
  • 一部のブラウザー (私が最初にこれに遭遇したのは Safari 3 であったと思います) は、実際にはdisplay:none;で iframe をロードしない場合があります。frameborder属性を設定するとvisibility:hidden、iframe が表示されなくなります。
  • マークアップで iframe 属性をabout:blank指定しないと、一部のブラウザー (または同様のページ) が読み込まれます。srchttps ページでは、安全でないコンテンツの警告が IE でスローされる可能性があります。
于 2012-06-13T15:31:00.763 に答える
0

次の 3 つのファイルを作成してみてください。

http://abc.com/main.html :

<!DOCTYPE html>
<html>
<head>
    <script>
    function SendMsg(id) {
        window.frames.invisible.location = 'http://xyz.com/invisible.html#' + id;
    }
    </script>
</head>
<body>
    <input type="button" id="Test" value="Call iFrame" onclick="SendMsg(this.id);">
    <iframe src="http://xyz.com/visible.html" name="visible" height="250" width="500"></iframe>
    <iframe name="invisible" height="0" width="0" style="display:none;"></iframe>
</body>
</html>

http://xyz.com/visible.html :

<!DOCTYPE html>
<html>
<head>
    <script>
    function Hi() {
        alert('Hi there!');
    }
    </script>
</head>
<body>
    <h1>Visible on xyz.com</h1>
</body>
</html>

http://xyz.com/invisible.html :

<!DOCTYPE html>
<html>
<head>
    <script>
    var sActionText = "";
    function CheckForMessages() {
        if (location.hash != sActionText) {
            sActionText = location.hash;
            var sAction = "";
            var oSplitActionText = sActionText.split("#");
            sAction = oSplitActionText[1];
            if (sAction == "Test") {
                parent.frames.visible.Hi();
            }
        }
    }
    setInterval(CheckForMessages, 200); 
    </script>
</head>
<body>
    <h1>Invisible on xyz.com</h1>
</body>
</html>

フレーム構造は次のとおりです。

       main
       /  \
      /    \
visible    invisible

visibleしたがって、からアクセスする必要がある場合はinvisible、次のように移動する必要があります。

parent.frames.visible.Hi()

今後は、車輪を再発明するのではなく、クロスドメイン通信にeasyXDMまたはjQuery postMessage プラグインを使用することをお勧めします。

于 2012-06-12T14:32:31.250 に答える
0

同じオリジン ポリシーが原因で、関数にアクセスできないのには理由があります。可能であれば、実際のセキュリティの問題が発生します。

于 2012-06-12T17:09:17.290 に答える