교차 출처 postMessage가 IE10에서 깨졌습니까?


91

나는 사소한 postMessage예제 를 만들려고 노력하고 있습니다 ...

  • IE10에서
  • 창 / 탭 간 (vs. iframe)
  • 기원을 넘어

이러한 조건 중 하나를 제거하면 잘 작동합니다. :-)

그러나 내가 말할 수있는 한, 윈도우 사이는 postMessage두 윈도우가 원점을 공유 할 때만 IE10에서 작동하는 것처럼 보입니다. (사실 이상하게도 그 행동은 그것보다 약간 더 관대합니다. 호스트 를 공유하는 두 개의 다른 출처 도 작동 하는 것 같습니다).

문서화 된 버그입니까? 해결 방법이나 기타 조언이 있습니까?

(참고 : 이 질문 은 문제에 관한 것이지만 대답 은 10이 아닌 IE8 및 IE9에 관한 입니다.)


자세한 내용 + 예 ...

런처 페이지 데모

<!DOCTYPE html>
<html>
  <script>
    window.addEventListener("message", function(e){
      console.log("Received message: ", e);
    }, false);
  </script>
  <button onclick="window.open('http://jsbin.com/ameguj/1');">
    Open new window
  </button>
</html>

시작된 페이지 데모

<!DOCTYPE html>
<html>
  <script>
    window.opener.postMessage("Ahoy!", "*");
  </script>
</html>

이것은 http://jsbin.com/ahuzir/1 에서 작동합니다. 두 페이지가 동일한 출처 (jsbin.com)에서 호스팅되기 때문입니다. 그러나 두 번째 페이지를 다른 곳으로 이동하면 IE10에서 실패합니다.



5
MessageChannel이 작동하기 위해 postMessage를 요구할 때 MessageChannel을 최선의 선택으로 나열하는 것보다 질문에 대답하는 것으로 수락 된 답변을 변경하는 것을 고려하십시오. 한 시간 이상 MessageChannel을 사용하여 실행 가능한 솔루션이 iframe 프록시임을 확인했습니다.
Akrikos 2014 년

1
window.open이 팝업 대화 상자 인 경우이를 완전히 피하고 js 모달에서 iframe을 사용할 수 있습니다. jQuery Dialog 또는 Bootstrap Modal 과 같은 것이 내가 구현 한 방법입니다. 그런 다음 window.parent.postMessageIE에서 사용할 수 있습니다 .
styfle 2015

내 대답으로 @Bosh은 여전히 오래된 예를 지원해야 불행한 사람은 우리에게 도움이 보인다대로 허용 답변으로 thatone 설정 줄래 2018에서 작동하는 것 같다 및 프록시 프레임이 필요하지 않습니다
브루노 Laurinec

답변:


62

이 답변을 처음 게시했을 때 착각했습니다. 실제로 IE10에서 작동하지 않습니다. 분명히 사람들은 이것이 다른 이유로 유용하다는 것을 알았으므로 후손을 위해 남겨두고 있습니다. 아래의 원래 답변 :


주목할만한 점 postMessage은 IE8과 IE9에서 별도의 창에 대한 출처가 아닌 것으로 링크 된 해당 답변의 링크 이지만 IE10이 등장하기 전에 2009에서 작성되었습니다. 그래서 나는 그것이 IE10에서 수정되었다는 표시로 받아들이지 않을 것입니다.

postMessage자체로 http://caniuse.com/#feat=x-doc-messaging 은 IE10에서 여전히 고장 났음을 나타내며, 이는 데모와 일치하는 것으로 보입니다. caniuse 페이지 는 관련성 높은 인용문이 포함 된 이 기사로 연결됩니다 .

Internet Explorer 8 이상은 부분적으로 문서 간 메시징을 지원합니다. 현재 iframe에서는 작동하지만 새 창에서는 작동하지 않습니다. 그러나 Internet Explorer 10은 MessageChannel을 지원합니다. Firefox는 현재 문서 간 메시징을 지원하지만 MessageChannel은 지원하지 않습니다.

따라서 가장 좋은 방법은 아마도 MessageChannel기반 코드 경로 를 가지고 postMessage존재하지 않는 경우 대체하는 것입니다. IE8 / IE9 지원은받지 못하지만 적어도 IE10에서는 작동합니다.

문서 MessageChannel: http://msdn.microsoft.com/en-us/library/windows/apps/hh441303.aspx


8
MessageChannel작동 하는 기반 코드 경로를 어떻게 만드 시겠습니까? postMessage채널의 포트를 다른 창으로 가져 오려면 여전히 기능 이 필요합니다 .
balpha

1
postMessageMessageChannelAPI 와 함께 사용하면 새 창과 출처에서 작동합니다. 작업이 조금 어색 하다고 생각하지만 기본적으로 postMessage('foo', '*')는 나쁘고 postMessage('foo', [messageChannel.port2])좋습니다.
ShZ

3
나는 평생 동안 최신 버전의 IE (11) 및 MessageChannel API를 사용하여 도메인 간 팝업 창에서 postMessage를 사용할 수 없습니다. 그리고 솔직히이 특정 시나리오가 작동해야 함을 나타내는이 답변 외에 InterWebs에서 다른 곳을 찾을 수 없습니다. 누구든지 그것이 작동한다는 것을 증명하는 예를 가리킬 수 있습니까? 나는 영원히 감사 할 것입니다.
Todd Menier 2014 년

4
MessageChannel은 postMessage가 작동하지 않는 것과 같은 이유로 작동하지 않아야합니다. Microsoft는 크로스 프로세스 마샬링을 수정해야합니다. blogs.msdn.com/b/ieinternals/archive/2009/09/15/…
EricLaw

9
이 대답은 우리에게 거짓된 희망을주기 때문에 성가시다. 대답은 : PostMessage가 MessageChannel을 작동시키기 위해 필요 하기 때문에 프록시 없이는 작동하지 않을 것입니다 (적어도 내가 본 모든 데모에서). 누군가가 postMessage 또는 postMessage ( 'name', '<domain>', [messageChannel.port2])없이 작동하는 MessageChannel의 데모를 보여주지 않는 한 (작동하도록 할 수 없습니다) 믿을 수 없습니다. 프록시 프레임없이 작동합니다.
Akrikos 2014 년

30

실행기와 동일한 호스트에 프록시 페이지를 만듭니다. 프록시 페이지 iframe에 원격 페이지로 설정된 소스가 있습니다. Cross-origin postMessage는 이제 IE10에서 다음과 같이 작동합니다.

  • 원격 페이지는 window.parent.postMessage데이터를 프록시 페이지로 전달하는 데 사용 합니다. iframe을 사용하므로 IE10에서 지원합니다.
  • 프록시 페이지는 window.opener.postMessage데이터를 실행기 페이지로 다시 전달하는 데 사용 합니다. 동일한 도메인에 있으므로 출처 간 문제가 없습니다. postMessage를 사용하지 않으려면 런처 페이지에서 전역 메소드를 직접 호출 할 수도 있습니다.window.opener.someMethod(data)

샘플 (모든 URL이 가상 임)

런처 페이지 http://example.com/launcher.htm

<!DOCTYPE html>
<html>
    <head>
        <title>Test launcher page</title>
        <link rel="stylesheet" href="/css/style.css" />
    </head>
    <body>

    <script>
        function log(msg) {
            if (!msg) return;

            var logger = document.getElementById('logger');
            logger.value += msg + '\r\n';
        }            

        function toJson(obj) {
            return JSON.stringify(obj, null, 2);
        }

        function openProxy() {
            var url = 'proxy.htm';
            window.open(url, 'wdwProxy', 'location=no');
            log('Open proxy: ' + url);
        }

        window.addEventListener('message', function(e) {
            log('Received message: ' + toJson(e.data));
        }, false);
    </script>
    
    <button onclick="openProxy();">Open remote</button> <br/>
    <textarea cols="150" rows="20" id="logger"></textarea>

    </body>
</html>

프록시 페이지 http://example.com/proxy.htm

<!DOCTYPE html>
<html>
    <head>
        <title>Proxy page</title>
        <link rel="stylesheet" href="/css/style.css" />
    </head>
    <body>

    <script>
        function toJson(obj) {
            return JSON.stringify(obj, null, 2);
        }

        window.addEventListener('message', function(e) {
            console.log('Received message: ' + toJson(e.data));

            window.opener.postMessage(e.data, '*');
            window.close(self);
        }, false);
    </script>

    <iframe src="http://example.net/remote.htm" frameborder="0" height="300" width="500" marginheight="0" marginwidth="0" scrolling="auto"></iframe>

    </body>
</html>

원격 페이지 http://example.net/remote.htm

<!DOCTYPE html>
<html>
    <head>
        <title>Remote page</title>
        <link rel="stylesheet" href="/css/style.css" />
    </head>
    <body>

    <script>
        function remoteSubmit() {
            var data = {
                message: document.getElementById('msg').value
            };

            window.parent.postMessage(data, '*');
        }
    </script>
    
    <h2>Remote page</h2>

    <input type="text" id="msg" placeholder="Type a message" /><button onclick="remoteSubmit();">Close</button>

    </body>
</html>

Microsoft 예제 페이지 및 다른 답변에 링크 된 해결 방법 페이지에 대한 링크가 포함되어 있으면 답변이 더 좋을 것입니다. 해결 방법 : blogs.msdn.com/b/ieinternals/archive/2009/09/16/… 예제 (해결 방법 페이지에서) : debugtheweb.com/test/xdm/origin
Akrikos

또한 예제 페이지는 이제 찾을 수없는 godaddy 페이지로 연결됩니다.
Akrikos 2014 년

8
응? ... 모든 URL은 예제이며 실제로 기존 페이지를 가리키는 것이 아닙니다. 나열된 소스에서 작업을 수행하기 위해 수행해야 할 작업을 결정할 수 있습니다 ..
LyphTEC 2014 년

설명해 주셔서 감사합니다. :-)
Akrikos 2014 년

29

== iframe없이 2020 년 작업 솔루션 ==

tangle에 의한 답변을 기반으로 다음 스 니펫을 사용하여 IE11 [및 에뮬레이트 된 IE10 모드]에서 성공했습니다.

var submitWindow = window.open("/", "processingWindow");
submitWindow.location.href = 'about:blank';
submitWindow.location.href = 'remotePage to comunicate with';

그런 다음 일반적인 postMessage 스택을 사용하여 통신 할 수 있었으며 시나리오에서 하나의 전역 정적 메신저를 사용하고 있습니다 (그것이 의미가 없다고 생각하지만 메신저 클래스도 첨부하고 있습니다).

var messagingProvider = {
    _initialized: false,
    _currentHandler: null,

    _init: function () {
        var self = this;
        this._initialized = true;
        var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
        var eventer = window[eventMethod];
        var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";

        eventer(messageEvent, function (e) {
            var callback = self._currentHandler;
            if (callback != null) {
                var key = e.message ? "message" : "data";
                var data = e[key];
                callback(data);
            }
        }, false);
    },

    post: function (target, message) {
        target.postMessage(message, '*');
    },

    setListener: function (callback) {
        if (!this._initialized) {
            this._init();
        }

        this._currentHandler = callback;
    }
}

아무리 노력해도 IE9와 IE8에서 작동하지 않았습니다.

작동중인 내 구성 :
IE 버전 : 11.0.10240.16590, 업데이트 버전 : 11.0.25 (KB3100773)


6
다른 사람이 "안 돼, 그건 고칠 수 없다"고 생각하는이 해결 방법을보고있는 경우를 대비해 실제로 IE11의 window.opener에 postMessage가 불가능한 문제를 해결했습니다. 믿을 수 없는.
dkr88

1
설마 ... 내가 노력 이일 같았다 않으며,이 문제를 "해결"
lmiguelmh

매력적이고 신비로운 작품 !! (IE10.0.9200, win7)
Simon

이 해결 방법에 대한 전체 예제를 제공 할 수 있습니까?
msm2020

1
@SidJonnala는 실제로는 아니지만 권장합니다. 실제 원격 페이지에 즉시 재 할당하고 페이지를로드하는 데 3-4 초가 걸리면 [가끔 발생할 수 있음] window.open ( '/') 페이지가로드되고 사용자를 혼란스럽게 할 위험이 있습니다
Bruno Laurinec

2

LyphTEC 및 Akrikos의 답변을 기반으로 한 또 다른 해결 방법 <iframe>은 빈 팝업 창에 빈 팝업 창 을 만드는 것 입니다. 이렇게하면 빈 팝업이 오프너와 동일한 출처를 갖기 때문에 별도의 프록시 페이지가 필요하지 않습니다.

런처 페이지 http://example.com/launcher.htm

<html>
  <head>
    <title>postMessage launcher</title>
    <script>
      function openWnd() {
        var w = window.open("", "theWnd", "resizeable,status,width=400,height=300"),
            i = w.document.createElement("iframe");

        i.src = "http://example.net/remote.htm";
        w.document.body.appendChild(i);

        w.addEventListener("message", function (e) {
          console.log("message from " + e.origin + ": " + e.data);

          // Send a message back to the source
          e.source.postMessage("reply", e.origin);
        });
      }
    </script>
  </head>
  <body>
    <h2>postMessage launcher</h2>
    <p><a href="javascript:openWnd();">click me</a></p>
  </body>
</html>

원격 페이지 http://example.net/remote.htm

<html>
  <head>
    <title>postMessage remote</title>
    <script>
      window.addEventListener("message", function (e) {
        alert("message from " + e.origin + ": " + e.data);
      });

      // Send a message to the parent window every 5 seconds
      setInterval(function () {
        window.parent.postMessage("hello", "*");
      }, 5000);
    </script>
  </head>
  <body>
    <h2>postMessage remote</h2>
  </body>
</html>

이것이 얼마나 취약한지는 모르겠지만 IE 11 및 Firefox 40.0.3에서 작동합니다.


1
... 이제 <iframe>IE 11 ( 11.0.9600.18036, 업데이트 버전 11.0.23 (KB3087038)) 에서 작동하지 않습니다 (팝업 창에서 방향으로 자동 실패 ). 최신 보안 업데이트 ( KB3087038 )가 관련 되었을 수 있습니다.
tangle

1

현재 (2014-09-02),이 문제에 대한 해결 방법을 자세히 설명하는 msdn 블로그 게시물 ( https://blogs.msdn.microsoft.com/ieinternals/2009)에 명시된대로 프록시 프레임을 사용하는 것이 가장 좋습니다. / 09 / 15 / html5-implementation-issues-in-ie8-and-later /

다음은 작동하는 예입니다. http://www.debugtheweb.com/test/xdm/origin/

팝업과 원본이 동일한 페이지에 프록시 프레임을 설정해야합니다. 을 사용하여 팝업에서 프록시 프레임으로 정보를 보냅니다 window.opener.frames[0]. 그런 다음 프록시 프레임에서 기본 페이지로 postMessage를 사용하십시오.


1

이 솔루션에는 사이트를 로컬 인트라넷 사이트가 아닌 Internet Explore의 신뢰할 수있는 사이트에 추가하는 것이 포함됩니다 . 이 솔루션은 Windows 10 / IE 11.0.10240.16384, Windows 10 / Microsoft Edge 20.10240.16384.0 및 Windows 7 SP1 / IE 10.0.9200.17148에서 테스트했습니다. 페이지는 인트라넷 영역에 포함되지 않아야합니다 .

따라서 Internet Explorer 구성 (도구> 인터넷 옵션> 보안> 신뢰할 수있는 사이트> 사이트)을 열고 페이지를 추가합니다. 여기서 *를 사용하여 모든 하위 도메인을 일치시킵니다. 페이지 로컬 인트라넷 사이트 (도구> 인터넷 옵션> 보안> 로컬 인트라넷> 사이트> 고급)에 나열되어 있지 않은지 확인합니다 . 브라우저를 다시 시작하고 다시 테스트하십시오.

Internet Explorer에서 신뢰할 수있는 사이트에 추가

Windows 10 / Microsoft Edge 에서는 제어판> 인터넷 옵션에서이 구성을 찾을 수 있습니다.

최신 정보

그래도 작동하지 않으면 도구> 인터넷 옵션> 고급 설정> Internet Explorer 설정 재설정 에서 모든 설정 을 재설정 한 다음 재설정 할 수 있습니다. 주의해서 사용하십시오 ! 그런 다음 시스템을 재부팅해야합니다. 그런 다음 신뢰할 수있는 사이트에 사이트를 추가합니다.

파일> 속성에서 또는 오른쪽 클릭을 사용하여 페이지가 어떤 영역에 있는지 확인합니다.

Internet Explorer의 페이지 속성

최신 정보

나는 회사 인트라넷에 있고 때로는 작동하고 때로는 작동하지 않습니다 (자동 구성? 심지어 회사 프록시를 비난하기 시작했습니다). 결국 나는이 솔루션 https://stackoverflow.com/a/36630058/2692914를 사용했습니다 .


0

이 Q는 오래되었지만 easyXDM의 용도입니다. html5 .postMessage를 지원하지 않는 브라우저를 발견했을 때 잠재적 인 폴백으로 확인해보세요.

https://easyxdm.net/

다양한 IE 버전에서 window.postMessage가 실패하는 Windows 또는 프레임간에 도메인 간 메시지를 보내기 위해 처리 할 필요가없는 VBObject 래퍼 및 모든 유형의 항목을 사용합니다 (그리고 Edge는 여전히 지원에 대해 100 % 확신 할 수 없습니다. Edge에는 있지만 .postMessage에 대한 해결 방법이 필요한 것 같습니다.)


-3

MessageChannel은이 시나리오에서 여전히 중단 된 postMessage에 의존하기 때문에 창 / 탭 사이의 IE 9-11에서 작동하지 않습니다. "가장 좋은"해결 방법은 window.opener (즉, window.opener.somefunction ( "somedata"))를 통해 함수를 호출하는 것입니다.

여기에 자세한 해결 방법


1
이는 질문의 전제 조건 중 하나 인 교차 오리진 설정에서는 작동하지 않습니다.
PhistucK 2014-06-15
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.