program tip

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

radiobox 2020. 9. 8. 07:51
반응형

교차 출처 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에서는 작동하지 않습니다. 분명히 사람들은 이것이 다른 이유로 유용하다는 것을 알았으므로 후손을 위해 남겨두고 있습니다. 아래의 원래 답변 :


주목할 가치가있는 것은 postMessageIE8과 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>

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

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

Then I was able to communicate using typical postMessage stack, I'm using one global static messenger in my scenario (alotough I don't suppose it's of any signifficance, I'm also attaching my messenger class)

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;
    }
}

No matter how hard I tried, I wasn't able to make things work on IE9 and IE8

My config where it's working:
IE version: 11.0.10240.16590, Update versions: 11.0.25 (KB3100773)


Building upon the answers by LyphTEC and Akrikos, another work-around is to create an <iframe> within a blank popup window, which avoids the need for a separate proxy page, since the blank popup has the same origin as its opener.

Launcher page at 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>

Remote page at 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>

I'm not sure how fragile this is, but it is working in IE 11 and Firefox 40.0.3.


Right now, (2014-09-02), Your best bet is to use a proxy frame as noted in the msdn blog post that details a workaround for this issue: https://blogs.msdn.microsoft.com/ieinternals/2009/09/15/html5-implementation-issues-in-ie8-and-later/

Here's the working example: http://www.debugtheweb.com/test/xdm/origin/

You need to set up a proxy frame on your page that has the same origin as the popup. Send information from the popup to the proxy frame using window.opener.frames[0]. Then use postMessage from the proxy frame to the main page.


This solution involves adding the site to Internet Explore's Trusted Sites and not in the Local Intranet sites. I tested this solution in Windows 10/IE 11.0.10240.16384, Windows 10/Microsoft Edge 20.10240.16384.0 and Windows 7 SP1/IE 10.0.9200.17148. The page must not be included in the Intranet Zone.

So open Internet Explorer configuration (Tools > Internet Options > Security > Trusted Sites > Sites), and add the page, here I use * to match all the subdomains. Make sure the page isn't listed in the Local intranet sites (Tools > Internet Options > Security > Local Intranet > Sites > Advanced). Restart your browser and test again.

Add to trusted sites in Internet Explorer

In Windows 10/Microsoft Edge you will find this configuration in Control Panel > Internet Options.

UPDATE

If this doesn't work you could try resetting all your settings in Tools > Internet Options > Advanced Settings > Reset Internet Explorer settings and then Reset: use it with caution! Then you will need to reboot your system. After that add the sites to the Trusted sites.

See in what zone your page is in File > Properties or using right click.

Page properties in internet explorer

UPDATE

I am in a corporate intranet and sometimes it works and sometimes it doesn't (automatic configuration? I even started to blame the corporate proxy). In the end I used this solution https://stackoverflow.com/a/36630058/2692914.


MessageChannel doesn't work for IE 9-11 between windows/tabs since it relies on postMessage, which is still broken in this scenario. The "best" workaround is to call a function through window.opener (ie. window.opener.somefunction("somedata") ).

Workaround in more detail here

참고URL : https://stackoverflow.com/questions/16226924/is-cross-origin-postmessage-broken-in-ie10

반응형