คุณใช้ window.postMessage ข้ามโดเมนได้อย่างไร?


89

ดูเหมือนว่าจุดของwindow.postMessageคือการอนุญาตให้มีการสื่อสารที่ปลอดภัยระหว่าง windows / frames ที่โฮสต์บนโดเมนต่างๆ แต่ดูเหมือนจะไม่อนุญาตให้ใช้ใน Chrome

นี่คือสถานการณ์:

  1. ฝัง <iframe> (พร้อมกับsrcโดเมน B * ) ในเพจบนโดเมน A
  2. <iframe> จะกลายเป็นแท็ก <script> เป็นส่วนใหญ่ในตอนท้ายของการดำเนินการ ...
  3. ฉันเรียก window.postMessage ( some_data , page_on_A )

<iframe> นั้นแน่นอนที่สุดในบริบทของโดเมน B และฉันยืนยันว่าจาวาสคริปต์ที่ฝังอยู่ใน <iframe> นั้นทำงานได้อย่างถูกต้องและเรียกpostMessageด้วยค่าที่ถูกต้อง

ฉันได้รับข้อความแสดงข้อผิดพลาดนี้ใน Chrome:

ไม่สามารถโพสต์ข้อความเพื่อ ผู้รับมีต้นกำเนิดB

นี่คือรหัสที่ลงทะเบียนผู้ฟังเหตุการณ์ข้อความในหน้า A:

window.addEventListener(
  "message",
  function (event) {
    // Do something
  },
  false);

ฉันลองโทรwindow.postMessage(some_data, '*')แล้วด้วย แต่สิ่งที่ทำคือระงับข้อผิดพลาด

ฉันพลาดจุดนี้ไปหรือเปล่าคือ window.postMessage (... ) ไม่ได้มีไว้สำหรับสิ่งนี้? หรือฉันแค่ทำมันผิดอย่างร้ายแรง?

* ข้อความประเภท Mime / html ซึ่งจะต้องคงอยู่


1
คุณอาจทราบเรื่องนี้แล้ว แต่ MDC มีบทสรุปที่ยอดเยี่ยมใน postMessage: developer.mozilla.org/en/DOM/window.postMessageสำหรับการใช้งาน FF อย่างชัดเจน แต่อาจมีบางอย่างที่อธิบายว่าเหตุใดจึงไม่ทำงาน
Pekka

คำตอบ:


79

นี่คือตัวอย่างที่ใช้งานได้บน Chrome 5.0.375.125

หน้า B (เนื้อหา iframe):

<html>
    <head></head>
    <body>
        <script>
            top.postMessage('hello', 'A');
        </script>
    </body>
</html>

สังเกตการใช้top.postMessageหรือparent.postMessageไม่window.postMessageที่นี่

หน้า A:

<html>
<head></head>
<body>
    <iframe src="B"></iframe>
    <script>
        window.addEventListener( "message",
          function (e) {
                if(e.origin !== 'B'){ return; } 
                alert(e.data);
          },
          false);
    </script>
</body>
</html>

A และ B ต้องเป็นอย่างนั้น http://domain.com

แก้ไข:

จากคำถามอื่นดูเหมือนว่าโดเมน (A และ B ที่นี่) ต้องมี/เพื่อpostMessageให้ทำงานได้อย่างถูกต้อง


3
เมื่อหน้า A ตรวจสอบที่มาของข้อความจุดเริ่มต้นจะไม่มีการต่อท้าย '/' ดูเหมือนจะไม่สำคัญว่าหน้า B ระบุการต่อท้าย "/" หรือไม่ สิ่งที่ควรทราบอีกประการหนึ่งคือ URL ควรเป็น URL ที่สมบูรณ์
Catch22

1
คำตอบนี้ทำให้ฉันสับสนเล็กน้อยและยังคงค้นหาคำตอบอยู่ blog.teamtreehouse.com/cross-domain-messaging-with-postmessageมีคำอธิบายที่ดีมากเกี่ยวกับ postMessage สิ่งที่สำคัญคือผู้ส่งข้อความรู้จักโดเมนของผู้รับ ในตัวอย่างข้างต้น A และ B ไม่จำเป็นต้องเป็นโดเมนเดียวกัน แต่ B ต้องรู้ว่า A. ใช้โดเมนอะไร
Greg Bogumil

7
คำถามเกี่ยวกับการข้ามโดเมน คำตอบที่ยอมรับคือเกี่ยวกับโดเมนเดียวกัน
stackular

@stackular ไม่เป๊ะ. A และ B สามารถเป็นโดเมนใดก็ได้ นั่นคือเหตุผลหลักของการมีpostMessage
ไมค์

1
+1. เราต้องการยืนยันว่าโซลูชันนี้ใช้ได้กับกรณีของเรา เรามีเพจที่มี iframe จากโดเมนอื่น โปรดทราบว่างานนี้เฉพาะในเบราว์เซอร์ Chrome ในขณะที่ Firefox เราจำเป็นต้องใช้window.parent.postMessageแทนด้านบน แม้ว่าเราจะไม่รู้ว่าสามารถใช้กับเบราว์เซอร์อื่นได้หรือไม่
rahmatns

24

คุณควรโพสต์ข้อความจากเฟรมถึงพาเรนต์หลังจากโหลดแล้ว

สคริปต์กรอบ:

$(document).ready(function() {
    window.parent.postMessage("I'm loaded", "*");
});

และฟังในผู้ปกครอง:

function listenMessage(msg) {
    alert(msg);
}

if (window.addEventListener) {
    window.addEventListener("message", listenMessage, false);
} else {
    window.attachEvent("onmessage", listenMessage);
}

ใช้ลิงค์นี้เพื่อดูข้อมูลเพิ่มเติม: http://en.wikipedia.org/wiki/Web_Messaging


2

คุณอาจพยายามส่งข้อมูลของคุณจาก mydomain.com ไปที่ www.mydomain.com หรือย้อนกลับโปรดทราบว่าคุณพลาด "www" http://mydomain.comและhttp://www.mydomain.comเป็นโดเมนที่แตกต่างกันกับ javascript


2
ในโปรเจ็กต์ที่ฉันกำลังทำฉันกำลังใช้file:/// อยู่เป็นไปได้ไหมที่จะได้รับข้อผิดพลาดของโดเมนเมื่อดึงเนื้อหาจากระบบไฟล์ภายในเครื่องเท่านั้น
Jacksonkr
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.