프로그래밍 방식으로 생성 된 <iframe>의 문서 개체에 액세스하려고 할 때 "액세스가 거부되었습니다."JavaScript 오류 (IE 전용)


80

JavaScript를 사용하여 <iframe> 요소를 만들고 DOM에 추가해야하는 프로젝트가 있습니다. 그런 다음 <iframe>에 콘텐츠를 삽입해야합니다. 제 3 자 웹 사이트에 삽입 될 위젯입니다.

페이지를로드하고 싶지 않기 때문에 <iframe>의 "src"속성을 설정하지 않았습니다. 오히려 CSS 또는 JavaScript가 상위 페이지와 충돌하지 않도록 삽입하는 콘텐츠를 격리 / 샌드 박스하는 데 사용됩니다. JSONP를 사용하여 서버에서 일부 HTML 콘텐츠를로드하고이 <iframe>에 삽입합니다.

한 가지 심각한 예외를 제외하고 잘 작동합니다. 6, 7, 8에서 확인) 내가 만든이 <iframe>의 문서 개체에 액세스하려고하면 "액세스가 거부되었습니다."오류가 발생합니다. 내가 테스트 한 다른 브라우저 (모든 주요 최신 브라우저)에서는 발생하지 않습니다.

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>의 창 개체에 대한 핸들이 있습니다. 문서 객체에 대해 더 깊이 이해할 수 없습니다.

도움이나 제안에 감사드립니다! 나는 이것에 대한 해결책을 찾는 데 도움을 줄 수있는 사람에게 빚을 질 것이다.


troy.onespot의 링크가 죽었습니다.
mbomb007

답변:


67

document.domain 속성이 부모 페이지에 설정되어 있으면 Internet Explorer에서 "액세스가 거부되었습니다."라는 메시지가 표시됩니다.

한숨. 네, 이것은 IE 문제입니다 (버그? 이런 종류의 불쾌함에 대한 문서화 된 표준이 없기 때문에 말하기 어렵습니다). 당신이 srcless은 iframe을 만들 때 그것은 수신 document.domain부모 문서에서는의 location.host대신으로 document.domain. 그 시점에서 당신은 그것을 바꿀 수 없기 때문에 거의 잃었습니다.

끔찍한 해결 방법은 srcjavascript : URL (urgh!)로 설정하는 것입니다.

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

그러나 어떤 이유로 이러한 문서는 document.domainIE의 스크립트에서 자체적으로 설정할 수 없으므로 (오래된 "지정되지 않은 오류")이를 사용하여 부모 (*) 사이의 다리를 다시 얻을 수 없습니다. 당신은 할 수 인스턴스화 된 후에는 부모 문서에 이야기 할 필요가 없습니다 위젯을 가정, 전체 문서의 HTML을 작성하는 데 사용합니다.

그러나 iframe JavaScript URL은 Safari에서 작동하지 않으므로 사용할 방법을 선택하려면 여전히 일종의 브라우저 스니핑이 필요합니다.

* : 다른 이유로 IE에서는 첫 번째 문서에 의해 작성된 두 번째 문서 인 document.에서 설정할 수 있습니다document.domain . 그래서 이것은 작동합니다.

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

이 시점에서 끔찍함 수준이 너무 높아서 나갑니다. 나는 David가 말한 것처럼 외부 HTML을 할 것입니다.


10
@bobince : 당신은 대단해! 나는 실제로 훨씬 더 많은 인터넷 검색 이후 어젯밤 늦게이 접근 방식을 우연히 발견했습니다. 사실, 저는 훨씬 더 강력하고 잠재적으로 덜 복잡한 크로스 브라우저 솔루션을 찾았을 것 같습니다 : telerik.com/community/forums/aspnet-ajax/editor/…-8 월 21 일에 Jeff Tucker의 게시물을 확인하세요. iframe>의 "src"속성이 "javascript : void ((function () {document.open (); document.domain = \ 'tld.com \'; document.close ();}) ())"로 보입니다. 트릭을 수행하고 브라우저 간 방식으로 수행합니다. Safari (최소 v3 이상)에서도 작동합니다.
Bungle

1
다음은 이전 의견을 보여주는 테스트 페이지입니다. troy.onespot.com/static/access_denied_test.html
Bungle

1
오 좋은! 훨씬 낫습니다! 직접 수행하는 것이 흥미 롭습니다. 일반적으로 javascript : URL은 부모의 컨텍스트에서 실행되지만 iframe src의 경우에는 그렇지 않은 것 같습니다. void()함수가 이미을 반환하기 때문에 호출을 잃을 수도 있습니다 undefined.
bobince

1
부수적으로 IE에서 iframe 위치를 유지하려고 시도하기 때문에 IE에서 페이지를 다시로드하는 동안 오류가 발생합니다. argh. 그 주위에 방법이 있다면 Dunno.
bobince

1
@bobince : 오, 당신이 맞아요. 지적 해 주셔서 감사합니다. 처음에는 너무 흥분해서 재 장전 할 필요가 없었습니다. IE가 <iframe> 위치를 유지하려고한다는 것은 무엇을 의미합니까? 이 문제에 대한 해결책을 찾아야하므로 계속 게시 해 드리겠습니다. 발견 한 내용이 있으면 똑같이하십시오.
Bungle

18

예, 액세스 예외는 document.domain부모와 iframe에서 일치해야 한다는 사실 때문이며, 일치하기 전에 iframe의 document.domain속성 을 프로그래밍 방식으로 설정할 수 없습니다 .

여기에서 가장 좋은 방법은 페이지를 자신의 템플릿으로 지정하는 것입니다.

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

그리고 myiframe.htm에서 :

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

3
고마워, 데이비드-확실한 제안으로 보이는 것에 감사하지만 마지막 수단이 아니라면이 접근 방식을 사용하지 않는 편입니다. 내가 올바르게 이해한다면 템플릿은 상위 페이지와 동일한 도메인에 있어야하며 (맞습니까?) 고객의 구현이 복잡해집니다. 이상적으로 구현은 페이지의 HTML에 몇 줄의 JavaScript를 삽입하는 것처럼 간단해야합니다.
Bungle

1
예, 솔루션은 바로 그 도메인에 다른 파일이 필요합니다. 하지만 그것이 제가 생각 해낼 수있는 최선의 방법이 아닐까 두렵습니다.
David Hedlund

1
@Bungle : 나는 그것이 당신의 유일한 선택이라고 생각합니다.
Tim Down

3

글쎄, 나는 실제로 매우 비슷한 문제가 있지만 비틀어 ... 최상위 사이트가 a.foo.com이라고 말하십시오-이제 문서 도메인을 a.foo.com으로 설정했습니다.

그런 다음 내가 생성 / 소유 한 iframe에서 a.foo.com도 설정했습니다.

내가 너무 foo.com을 설정할 수 없다는 점에 유의하십시오 .b / c 페이지에 bafoo.com을 가리키는 다른 iframe이 있습니다 (다시 a.foo.com을 사용하지만 스크립트 코드를 변경할 수 없습니다)

당신은 본질적으로 document.domain을 어쨌든 이미 설정 한 것으로 설정한다는 것을 알 수 있습니다 ...하지만 bafoo.com에서 언급 한 다른 iframe에 액세스하려면 그렇게해야합니다.

내 프레임 내에서 도메인을 설정 한 후 모든 iframe이 동일한 설정을 갖더라도 IE 6/7에서 부모에 도달 할 때 여전히 오류가 발생합니다.

r 정말 비 자리 다른 것들이 있습니다

외부 / 최상위 수준에서 onload 이벤트를 기다렸다가 타이머를 설정하면 결국 액세스해야하는 프레임에 도달 할 수 있습니다 ....하지만 아래에서 위로 도달 할 수는 없습니다. 할 수 있어야

또한 모든 것을 foo.com으로 설정하면 (내가 말한대로 할 수 없습니다) 작동합니다! 그러나 어떤 이유로, location.host와 같은 값을 사용할 때 .... 그것은 나를 죽이는 것입니다 .....


2

나는 단지 사용 <iframe src="about:blank" ...></iframe>하고 잘 작동합니다.


2

IE의 경우 포트가 중요합니다. 도메인 간에는 동일한 포트 여야합니다.


1

jQuery.contents () 사용해 보셨습니까 ?


1
Deniss, 좋은 제안 및 감사합니다. 한 번 해보았 지만 (< troy.onespot.com/static/access_denied_jquery.html> 참조 ) 비슷한 오류가 발생했습니다. 이번에는 jQuery 스크립트 내에서 "Permission denied"입니다. 나는 그것이 동일하거나 유사한 장애물이라고 생각합니다.
Bungle

1
죄송합니다. URL이 망가졌습니다. 시도 : troy.onespot.com/static/access_denied_jquery.html
Bungle

4
jQuery가 iframe의 문서에 마법처럼 액세스 할 수있는 이유는 무엇입니까?
Tim Down

8
@Tim Down : jQuery가 마법 같은 접근 권한을 가질 것이라는 가정은 생각하지 않습니다. 오히려 jQuery는 종종 브라우저 간 문제를 해결하기 위해 몇 가지 멋진 트릭을 가지고 있으며 이미 해결 방법을 구현했을 수 있습니다. 나는 그것이 좋은 징조가 아니라는 데 동의하지만 좋은 제안이었고 한 번의 가치가 있다고 생각합니다.
Bungle

이것은 정말로 대답이 아닙니다. 제안 일 뿐이며 원래 게시물에 대한 댓글로 더 좋을 것입니다.
Neil Monroe

1

IE의 문제는 document.frames 객체를 통해 iframe에 액세스하려고 할 때 발생하는 것 같습니다. 생성 된 iframe에 대한 참조를 변수에 저장하면 변수 (아래 코드에서 my_iframe)를 통해 삽입 된 iframe에 액세스 할 수 있습니다. ).

IE6 / 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
감사. 이것은 나를 위해 문제를 해결 한 것 같습니다.
vit

1
이상한 점은 제가 사용하던 것과 똑같다는 것입니다. 잘 작동했습니다. 이제 갑자기 getttig access denied 오류가 계속 발생합니다
frostymarvelous

1

비슷한 문제가 있었고 해결책은이 코드 스 니펫 (IE8 / 9, Chrome 및 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>');

몇 가지 방법을 시도했지만 이것이 가장 좋은 것 같습니다. 여기 내 블로그 게시물에서 몇 가지 설명을 찾을 수 있습니다 .


1

Andralor의 매우 간단한 방법에 따라 여기에서 문제가 해결되었습니다. https://github.com/fancyapps/fancyBox/issues/766

기본적으로 iframe을 다시 onUpdate로 호출합니다.

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

-2

IE는 다른 모든 브라우저와 마찬가지로 iframe에서 작동합니다 (적어도 주요 기능의 경우). 규칙 세트를 유지하기 만하면됩니다.

  • iframe (iframe 부모에 대해 알아야하는 js 부분)에 자바 스크립트를로드하기 전에 부모가 document.domain이 변경되었는지 확인합니다.
  • 모든 iframe 리소스가로드되면 document.domain을 부모에 정의 된 것과 동일하게 변경합니다. (도메인을 설정하면 iframe 리소스의 요청이 실패하므로 나중에이 작업을 수행해야합니다.)

  • 이제 부모 창에 대한 참조를 만들 수 있습니다. var winn = window.parent

  • 이제 부모 HTML을 조작하기 위해 참조를 만들 수 있습니다. var parentContent = $ ( 'html', winn.document)
  • 이 시점에서 IE 부모 창 / 문서에 대한 액세스 권한이 있어야하며 원하지 않는대로 변경할 수 있습니다.

-11

나를 위해 더 나은 대답은 액세스가 거부되는 파일 허용을 확인하는 것입니다.

방금 jQuery-1.8.0.js로 업데이트하고 IE9에서 액세스 거부 오류가 발생했습니다.

Windows 탐색기에서

  • 속성을 선택한 파일을 마우스 오른쪽 버튼으로 클릭했습니다.
  • 보안 탭을 선택했습니다.
  • 고급 버튼을 클릭
  • 소유자 탭을 선택했습니다.
  • 편집 버튼을 클릭
  • 선택한 관리자 (MachineName \ Administrators)
  • 적용을 클릭
  • 모든 창문을 닫았습니다.

사이트를 테스트했습니다. 더 이상 문제가 없습니다.

방금 업데이트 한 jQuery-UI 스크립트에 대해서도 동일한 작업을 수행해야했습니다.


2
나는 당신이 다른 문제를 해결하고 있다고 생각합니다.
Danyal Aytekin

5
OP는 타사 위젯을 구축하고 있습니다. 모든 방문자가 위젯을 표시하기 위해이 모든 단계를 따르기를 기대할 수는 없습니다.
Christophe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.