window.postMessage
åºçº¿
广æ³å¯ç¨
èª 2015å¹´7æ èµ·ï¼æ¤ç¹æ§å·²å¨ä¸»æµæµè§å¨ä¸å¾å°æ¯æï¼å¯å¨å¤§å¤æ°è®¾å¤åæµè§å¨çæ¬ä¸æ£å¸¸ä½¿ç¨ã
window.postMessage() æ¹æ³å¯ä»¥å®å
¨å°å®ç°è·¨æºéä¿¡ãé常ï¼å¯¹äºä¸¤ä¸ªä¸å页é¢çèæ¬ï¼åªæå½æ§è¡å®ä»¬ç页é¢ä½äºå
·æç¸åçåè®®ï¼é常为 httpsï¼ï¼ç«¯å£å·ï¼443 为 https çé»è®¤å¼ï¼ï¼ä»¥åä¸»æº (两个页é¢çæ¨¡æ° Document.domain设置为ç¸åçå¼) æ¶ï¼è¿ä¸¤ä¸ªèæ¬æè½ç¸äºéä¿¡ãwindow.postMessage() æ¹æ³æä¾äºä¸ç§åæ§æºå¶æ¥è§é¿æ¤éå¶ï¼åªè¦æ£ç¡®ç使ç¨ï¼è¿ç§æ¹æ³å°±å¾å®å
¨ã
ä»å¹¿ä¹ä¸è®²ï¼ä¸ä¸ªçªå£å¯ä»¥è·å¾å¯¹å¦ä¸ä¸ªçªå£çå¼ç¨ï¼æ¯å¦ targetWindow = window.openerï¼ï¼ç¶åå¨çªå£ä¸è°ç¨ targetWindow.postMessage() æ¹æ³ååä¸ä¸ª MessageEvent æ¶æ¯ãæ¥æ¶æ¶æ¯ççªå£å¯ä»¥æ ¹æ®éè¦èªç±å¤çæ¤äºä»¶ãä¼ éç» window.postMessage() çåæ°ï¼æ¯å¦ messageï¼å°éè¿æ¶æ¯äºä»¶å¯¹è±¡æ´é²ç»æ¥æ¶æ¶æ¯ççªå£ã
è¯æ³
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow-
å ¶ä»çªå£çä¸ä¸ªå¼ç¨ï¼æ¯å¦ iframe ç contentWindow 屿§ãæ§è¡window.openè¿åççªå£å¯¹è±¡ãæè æ¯å½åè¿ææ°å¼ç´¢å¼çwindow.framesã
message-
å°è¦åéå°å ¶ä» window çæ°æ®ãå®å°ä¼è¢«ç»æåå éç®æ³åºååãè¿æå³çä½ å¯ä»¥ä¸åä»ä¹éå¶çå°æ°æ®å¯¹è±¡å®å ¨çä¼ éç»ç®æ çªå£èæ éèªå·±åºååã[1]
targetOrigin-
éè¿çªå£ç origin 屿§æ¥æå®åªäºçªå£è½æ¥æ¶å°æ¶æ¯äºä»¶ï¼å ¶å¼å¯ä»¥æ¯å符串"*"ï¼è¡¨ç¤ºæ éå¶ï¼æè ä¸ä¸ª URIãå¨åéæ¶æ¯çæ¶åï¼å¦æç®æ çªå£çåè®®ã主æºå°åæç«¯å£è¿ä¸è çä»»æä¸é¡¹ä¸å¹é targetOrigin æä¾çå¼ï¼é£ä¹æ¶æ¯å°±ä¸ä¼è¢«åéï¼åªæä¸è å®å ¨å¹é ï¼æ¶æ¯æä¼è¢«åéãè¿ä¸ªæºå¶ç¨æ¥æ§å¶æ¶æ¯å¯ä»¥åéå°åªäºçªå£ï¼ä¾å¦ï¼å½ç¨ postMessage ä¼ éå¯ç æ¶ï¼è¿ä¸ªåæ°å°±æ¾å¾å°¤ä¸ºéè¦ï¼å¿ é¡»ä¿è¯å®çå¼ä¸è¿æ¡å å«å¯ç çä¿¡æ¯ç颿æ¥åè ç origin 屿§å®å ¨ä¸è´ï¼æ¥é²æ¢å¯ç è¢«æ¶æçç¬¬ä¸æ¹æªè·ãå¦æä½ æç¡®çç¥éæ¶æ¯åºè¯¥åéå°åªä¸ªçªå£ï¼é£ä¹è¯·å§ç»æä¾ä¸ä¸ªæç¡®åå¼ç targetOriginï¼è䏿¯ *ã䏿ä¾ç¡®åçç®æ å°å¯¼è´æ°æ®æ³é²å°ä»»ä½å¯¹æ°æ®æå ´è¶£çæ¶æç«ç¹ã
transferå¯é-
æ¯ä¸ä¸²å message åæ¶ä¼ éç
Transferable对象ãè¿äºå¯¹è±¡çæææå°è¢«è½¬ç§»ç»æ¶æ¯çæ¥æ¶æ¹ï¼èåé䏿¹å°ä¸åä¿ææææã
The dispatched event
æ§è¡å¦ä¸ä»£ç ï¼å ¶ä» window å¯ä»¥çå¬ååç message:
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
// For Chrome, the origin property is in the event.originalEvent
// object.
// è¿éä¸åç¡®ï¼chrome 没æè¿ä¸ªå±æ§
// var origin = event.origin || event.originalEvent.origin;
var origin = event.origin;
if (origin !== "http://example.org:8080") return;
// ...
}
message ç屿§æï¼
data-
ä»å ¶ä» window ä¸ä¼ éè¿æ¥ç对象ã
origin-
è°ç¨
postMessageæ¶æ¶æ¯åéæ¹çªå£ç origin . è¿ä¸ªåç¬¦ä¸²ç± åè®®ãâ://âãååãâ : 端å£å·âæ¼æ¥èæãä¾å¦âhttps://example.org(éå«ç«¯å£443)âãâhttp://example.net(éå«ç«¯å£80)âãâhttp://example.com:8080âã请注æï¼è¿ä¸ª origin ä¸è½ä¿è¯æ¯è¯¥çªå£çå½åææªæ¥ originï¼å 为 postMessage 被è°ç¨åå¯è½è¢«å¯¼èªå°ä¸åçä½ç½®ã source-
对åéæ¶æ¯ççªå£å¯¹è±¡çå¼ç¨; ä½ å¯ä»¥ä½¿ç¨æ¤æ¥å¨å ·æä¸å origin ç两个çªå£ä¹é´å»ºç«ååéä¿¡ã
å®å ¨é®é¢
å¦æä½ ä¸å¸æä»å ¶ä»ç½ç«æ¥æ¶ messageï¼è¯·ä¸è¦ä¸º message äºä»¶æ·»å ä»»ä½äºä»¶ä¾¦å¬å¨ã è¿æ¯ä¸ä¸ªå®å ¨ä¸æ ä¸å¤±çæ¹å¼æ¥é¿å å®å ¨é®é¢ã
å¦æä½ ç¡®å®å¸æä»å
¶ä»ç½ç«æ¥æ¶ messageï¼è¯·å§ç»ä½¿ç¨ origin å source 屿§éªè¯å件人ç身份ãä»»ä½çªå£ï¼å
æ¬ä¾å¦ http://evil.example.comï¼é½å¯ä»¥åä»»ä½å
¶ä»çªå£åéæ¶æ¯ï¼å¹¶ä¸ä½ ä¸è½ä¿è¯æªç¥å件人ä¸ä¼åéæ¶ææ¶æ¯ã使¯ï¼éªè¯èº«ä»½åï¼ä½ ä»ç¶åºè¯¥å§ç»éªè¯æ¥æ¶å°çæ¶æ¯çè¯æ³ãå¦åï¼ä½ ä¿¡ä»»åªåéåä¿¡ä»»é®ä»¶çç½ç«ä¸çå®å
¨æ¼æ´å¯è½ä¼å¨ä½ çç½ç«ä¸æå¼è·¨ç½ç«èæ¬æ¼æ´ã
å½ä½ ä½¿ç¨ postMessage å°æ°æ®åéå°å ¶ä»çªå£æ¶ï¼å§ç»æå®ç²¾ç¡®çç®æ originï¼è䏿¯ *ã æ¶æç½ç«å¯ä»¥å¨ä½ ä¸ç¥æ çæ åµä¸æ´æ¹çªå£çä½ç½®ï¼å æ¤å®å¯ä»¥æ¦æªä½¿ç¨ postMessage åéçæ°æ®ã
示ä¾
/*
* A çªå£çå忝<http://example.com:8080>ï¼ä»¥ä¸æ¯ A çªå£ç script æ ç¾ä¸ç代ç ï¼
*/
var popup = window.open(...popup details...);
// å¦æå¼¹åºæ¡æ²¡æè¢«é»æ¢ä¸å è½½å®æ
// è¿è¡è¯å¥æ²¡æåéä¿¡æ¯åºå»ï¼å³ä½¿å设å½å页颿²¡ææ¹å locationï¼å 为 targetOrigin 设置ä¸å¯¹ï¼
popup.postMessage("The user is 'bob' and the password is 'secret'",
"https://secure.example.net");
// å设å½å页颿²¡ææ¹å locationï¼è¿æ¡è¯å¥ä¼æåæ·»å message å°åééåä¸å»ï¼targetOrigin 设置对äºï¼
popup.postMessage("hello there!", "http://example.com");
function receiveMessage(event)
{
// æä»¬è½ç¸ä¿¡ä¿¡æ¯çåéè
åï¼(ä¹è®¸è¿ä¸ªåéè
åæä»¬æåæå¼ç䏿¯åä¸ä¸ªé¡µé¢).
if (event.origin !== "http://example.com")
return;
// event.source æ¯æä»¬éè¿ window.open æå¼çå¼¹åºé¡µé¢ popup
// event.data æ¯ popup åéç»å½å页é¢çæ¶æ¯ "hi there yourself! the secret response is: rheeeeet!"
}
window.addEventListener("message", receiveMessage, false);
/*
* å¼¹åºé¡µ popup å忝 http://example.comï¼ä»¥ä¸æ¯ script æ ç¾ä¸ç代ç ï¼
*/
//å½ A é¡µé¢ postMessage 被è°ç¨åï¼è¿ä¸ª function 被 addEventListener è°ç¨
function receiveMessage(event) {
// æä»¬è½ä¿¡ä»»ä¿¡æ¯æ¥æºåï¼
if (event.origin !== "http://example.com:8080") return;
// event.source å°±å½åå¼¹åºé¡µçæ¥æºé¡µé¢
// event.data æ¯ "hello there!"
// åè®¾ä½ å·²ç»éªè¯äºæåå°ä¿¡æ¯ç origin (任使¶åä½ é½åºè¯¥è¿æ ·å), ä¸ä¸ªå¾æ¹ä¾¿çæ¹å¼å°±æ¯æ event.source
// ä½ä¸ºåä¿¡ç对象ï¼å¹¶ä¸æ event.origin ä½ä¸º targetOrigin
event.source.postMessage(
"hi there yourself! the secret response " + "is: rheeeeet!",
event.origin,
);
}
window.addEventListener("message", receiveMessage, false);
注æ
ä»»ä½çªå£å¯ä»¥å¨ä»»ä½å
¶ä»çªå£è®¿é®æ¤æ¹æ³ï¼å¨ä»»ä½æ¶é´ï¼æ è®ºææ¡£å¨çªå£ä¸çä½ç½®ï¼åå
¶åéæ¶æ¯ãå æ¤ï¼ç¨äºæ¥æ¶æ¶æ¯çä»»ä½äºä»¶çå¬å¨å¿
é¡»é¦å
ä½¿ç¨ origin å source 屿§æ¥æ£æ¥æ¶æ¯çåéè
çèº«ä»½ãæ æ³æ£æ¥ origin å source 屿§ä¼å¯¼è´è·¨ç«ç¹èæ¬æ»å»ã
ä¸ä»»ä½å¼æ¥è°åº¦çèæ¬ï¼è¶ æ¶ï¼ç¨æ·çæçäºä»¶ï¼ä¸æ ·ï¼postMessage çè°ç¨è ä¸å¯è½æ£æµå°ä¾¦å¬ç± postMessage åéçäºä»¶çäºä»¶å¤çç¨åºä½æ¶æåºå¼å¸¸ã
åæ´¾äºä»¶ç origin 屿§çå¼ä¸åè°ç¨çªå£ä¸ document.domain çå½åå¼çå½±åã
ä» å¯¹äº IDN 主æºåï¼origin 屿§çå¼ä¸æ¯å§ç»ä¸º Unicode æ punycode; å¨ä½¿ç¨æ¤å±æ§æ¶ï¼å¦æä½ æææ¥èª IDN ç½ç«çæ¶æ¯ï¼åæå¤§ç¨åº¦å°å ¼å®¹æ§æ£æ¥ IDN å punycode å¼ãè¿ä¸ªå¼æç»å°å§ç»æ¯ IDNï¼ä½ç°å¨ä½ åºè¯¥åæ¶å¤ç IDN å punycode 表åã
å½åéçªå£å
å« javascript: æ data: URL æ¶ï¼origin 屿§ç弿¯å è½½ URL çèæ¬ç
卿©å±ä¸ä½¿ç¨ window.postMessage
window.postMessage å¯ç¨äºä»¥ chrome 代ç è¿è¡ç JavaScriptï¼ä¾å¦ï¼å¨æ©å±åç¹æä»£ç ä¸ï¼ï¼ä½æ¯åæ´¾äºä»¶ç source 屿§æ»æ¯ä¸ºç©ºä½ä¸ºå®å
¨éå¶ãï¼å
¶ä»å±æ§å
·æå
¶ææå¼ãï¼åéå°ä½äº chromeï¼URL ççªå£çæ¶æ¯ç targetOrigin åæ°å½å被é误解éï¼ä½¿å¾å°å¯¼è´åéæ¶æ¯çå¯ä¸å¼ä¸º "*"ãç±äºæ¤å¼æ¯ä¸å®å
¨çï¼å½ç®æ çªå£å¯ä»¥å¯¼èªå°å
¶ä»å°æ¹çæ¶æç½ç«ï¼å»ºè®® postMessage ä¸ç¨äºä¸ chromeï¼é¡µé¢çæ²é; 使ç¨ä¸åçæ¹æ³ï¼å¦æå¼çªå£æ¶çæ¥è¯¢å符串ï¼ä¸ chrome çªå£è¿è¡éä¿¡ãæåï¼å¨æä»¶ä¸å页é¢å叿¶æ¯ï¼URL å½åè¦æ± targetOrigin åæ°ä¸º "*"ãfile://ä¸è½ç¨ä½å®å
¨éå¶; è¿ä¸ªéå¶å¯è½ä¼å¨å°æ¥è¢«ä¿®æ¹ã
è§è
| è§è |
|---|
| HTML > # dom-window-postmessage-options-dev > |