1. ホーム
  2. javascript

プログラムで作成された<iframe>のドキュメントオブジェクトにアクセスしようとすると、"Access is denied" というJavaScriptエラーが発生する(IEのみ)

2023-08-09 17:30:02

質問

JavaScriptを使用して<iframe>要素を作成し、それをDOMに追加する必要があるプロジェクトがあります。その後、いくつかのコンテンツを<iframe>に挿入する必要があります。これは、サードパーティのWebサイトに埋め込まれるウィジェットです。

ページをロードしたくないので、"src" 属性を設定しません。むしろ、親ページと CSS または JavaScript の競合が発生しないように、挿入するコンテンツを分離/サンドボックス化するために使用されます。JSONP を使用して、サーバーから HTML コンテンツを読み込み、この <iframe> に挿入しています。

親ページで document.domain プロパティが設定されている場合 (このウィジェットが配置されている特定の環境ではそうであるかもしれません)、Internet Explorer (おそらくすべてのバージョンですが、6、7、8 で確認しました) では、作成したこの <iframe> のドキュメント オブジェクトにアクセスしようとすると "Access is denied" エラーを表示します。私がテストした他のブラウザ(主要な最新のものすべて)では発生しません。

Internet Explorer では、互いに通信するすべてのウィンドウ/フレームの document.domain を同じ値に設定する必要があることを承知しているので、これはある程度理にかなっています。しかし、アクセスできないドキュメントにこの値を設定する方法については、私は認識していません。

どなたか、これを行う方法、つまり、動的に作成されたこの <iframe> の document.domain プロパティを設定する方法をご存知でしょうか?または、正しい角度から見ていないのでしょうか。この問題に遭遇することなく、私が目指していることを達成する別の方法があるのでしょうか。このウィジェットの機能にとって、隔離されたサンドボックスのウィンドウが重要であるため、いずれにせよ <iframe> を使用する必要があります。

これが私のテストコードです。

<!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> のウィンドウ オブジェクトのハンドルを取得しています。

どんなヘルプや提案でも本当にありがとうございます。私は、この解決策を見つけるのを助けることができる人に恩義を感じるでしょう。

どのように解決するのですか?

<ブロッククオート

親ページにdocument.domainプロパティが設定されている場合、Internet Explorerで"Access is denied"が表示されます。

はぁー。ええ、IEの問題です(バグ?この種の不愉快なことに関する文書化された標準がないので言いにくい)。srcless iframe を作成すると、そのフレームは document.domain を親文書の location.host の代わりに document.domain . この時点で、あなたはそれを変更することができないので、かなり損をしています。

ひどい回避策は src をjavascriptに変換することです。の URL に設定することです (うっ!)。

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

しかし、何らかの理由で、このようなドキュメントは、自分自身の document.domain をスクリプトから設定することができないので(古き良き "unspecified error")、それを使って親(*)の間のブリッジを取り戻すことはできません。あなたは ができた ウィジェットが一度インスタンス化されると、その親ドキュメントと話す必要がないと仮定すると、ドキュメント全体の HTML を書くためにそれを使用することができます。

しかし iframe JavaScript の URL は Safari では動作しないので、使用する方法を選択するために、何らかのブラウザ スニッフィングが必要でしょう。

*: 他の何らかの理由で できる を、IE では document.domain を、最初のドキュメントによって書かれた第二のドキュメント、document.writtenから設定することができます。だから、これは動作します。

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

この時点で隠蔽体質が高すぎてアウトです。Davidが言ったように外部HTMLにします。