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

나는 사소한 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에서 실패합니다.



답변

이 답변을 처음 게시했을 때 착각했습니다. 실제로 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


답변

실행기와 동일한 호스트에 프록시 페이지를 만듭니다. 프록시 페이지 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>


답변

== 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)


답변

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에서 작동합니다.


답변

현재 (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를 사용하십시오.


답변

이 솔루션에는 사이트를 로컬 인트라넷 사이트가 아닌 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를 사용했습니다 .


답변

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

https://easyxdm.net/

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