window.postMessage()
method safely enables cross-origin communication between
Window
objects;
e.g.,
between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.
Normally, scripts on different pages are allowed to access each other if and only if the pages they originate from share the same protocol, port number, and host (also known as the "
same-origin policy
").
window.postMessage()
provides a controlled mechanism to securely circumvent this restriction (if used properly).
Broadly, one window may obtain a reference to another (
e.g.,
凭借
targetWindow = window.opener
), and then dispatch a
MessageEvent
on it with
targetWindow.postMessage()
. The receiving window is then free to
handle this event
as needed. The arguments passed to
window.postMessage()
(
i.e.,
the “message”) are
exposed to the receiving window through the event object
.
targetWindow.postMessage(message, targetOrigin, [transfer]);
targetWindow
window.open
(to spawn a new window and then reference it),
window.opener
(to reference the window that spawned this one),
HTMLIFrameElement.contentWindow
(to reference an embedded
<iframe>
from its parent window),
window.parent
(to reference the parent window from within an embedded
<iframe>
),或
window.frames
+ an index value (named or numeric).
message
targetOrigin
targetWindow
must be for the event to be dispatched, either as the literal string
"*"
(indicating no preference) or as a URI. If at the time the event is scheduled to be dispatched the scheme, hostname, or port of
targetWindow
's document does not match that provided in
targetOrigin
, the event will not be dispatched; only if all three match will the event be dispatched. This mechanism provides control over where messages are sent; for example, if
postMessage()
was used to transmit a password, it would be absolutely critical that this argument be a URI whose origin is the same as the intended receiver of the message containing the password, to prevent interception of the password by a malicious third party.
Always provide a specific
targetOrigin
, not
*
, if you know where the other window's document should be located. Failing to provide a specific target discloses the data you send to any interested malicious site.
transfer
可选
Transferable
objects that are transferred with the message. The ownership of these objects is given to the destination side and they are no longer usable on the sending side.
otherWindow
can listen for dispatched messages by executing the following JavaScript:
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
if (event.origin !== "http://example.org:8080")
return;
// ...
}
The properties of the dispatched message are:
data
The object passed from the other window.
origin
postMessage
was called. This string is the concatenation of the protocol and "://", the host name if one exists, and ":" followed by a port number if a port is present and differs from the default port for the given protocol. Examples of typical origins are
https://example.org
(implying port
443
),
http://example.net
(implying port
80
),和
http://example.com:8080
. Note that this origin is
not
guaranteed to be the current or future origin of that window, which might have been navigated to a different location since
postMessage
被调用。
source
window
object that sent the message; you can use this to establish two-way communication between two windows with different origins.
If you do not expect to receive messages from other sites,
do not
add any event listeners for
message
事件。
This is a completely foolproof way to avoid security problems.
If you do expect to receive messages from other sites,
always verify the sender's identity
使用
origin
and possibly
source
properties. Any window (including, for example,
http://evil.example.com
) can send a message to any other window, and you have no guarantees that an unknown sender will not send malicious messages. Having verified identity, however, you still should
always verify the syntax of the received message
. Otherwise, a security hole in the site you trusted to send only trusted messages could then open a cross-site scripting hole in your site.
Always specify an exact target origin, not
*
, when you use
postMessage
to send data to other windows.
A malicious site can change the location of the window without your knowledge, and therefore it can intercept the data sent using
postMessage
.
若
postMessage()
throws when used with
SharedArrayBuffer
objects, you might need to make sure you cross-site isolated your site properly. Shared memory is gated behind two HTTP headers:
Cross-Origin-Opener-Policy
with
same-origin
as value (protects your origin from attackers)
Cross-Origin-Embedder-Policy
with
require-corp
as value (protects victims from your origin)
Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp
To check if cross origin isolation has been successful, you can test against the
crossOriginIsolated
property available to window and worker contexts:
if (crossOriginIsolated) {
// Post SharedArrayBuffer
} else {
// Do something else
}
另请参阅 Planned changes to shared memory which is starting to roll out to browsers (Firefox 79, for example).
/*
* In window A's scripts, with A being on <http://example.com:8080>:
*/
var popup = window.open(/* popup details */);
// When the popup has fully loaded, if not blocked by a popup blocker:
// This does nothing, assuming the window hasn't changed its location.
popup.postMessage("The user is 'bob' and the password is 'secret'",
"https://secure.example.net");
// This will successfully queue a message to be sent to the popup, assuming
// the window hasn't changed its location.
popup.postMessage("hello there!", "http://example.com");
function receiveMessage(event)
{
// Do we trust the sender of this message? (might be
// different from what we originally opened, for example).
if (event.origin !== "http://example.com")
return;
// event.source is popup
// event.data is "hi there yourself! the secret response is: rheeeeet!"
}
window.addEventListener("message", receiveMessage, false);
/*
* In the popup's scripts, running on <http://example.com>:
*/
// Called sometime after postMessage is called
function receiveMessage(event)
{
// Do we trust the sender of this message?
if (event.origin !== "http://example.com:8080")
return;
// event.source is window.opener
// event.data is "hello there!"
// Assuming you've verified the origin of the received message (which
// you must do in any case), a convenient idiom for replying to a
// message is to call postMessage on event.source and provide
// event.origin as the targetOrigin.
event.source.postMessage("hi there yourself! the secret response " +
"is: rheeeeet!",
event.origin);
}
window.addEventListener("message", receiveMessage, false);
Any window may access this method on any other window, at any time, regardless of the location of the document in the window, to send it a message. Consequently, any event listener used to receive messages
must
first check the identity of the sender of the message, using the
origin
and possibly
source
properties. This cannot be overstated:
Failure to check the
origin
and possibly
source
properties enables cross-site scripting attacks.
As with any asynchronously-dispatched script (timeouts, user-generated events), it is not possible for the caller of
postMessage
to detect when an event handler listening for events sent by
postMessage
throws an exception.
postMessage()
schedules the
MessageEvent
to be dispatched
only after all pending execution contexts have finished
. For example, if
postMessage()
is invoked in an event handler, that event handler will run to completion, as will any remaining handlers for that same event, before the
MessageEvent
is dispatched.
值对于
origin
property of the dispatched event is not affected by the current value of
document.domain
in the calling window.
For IDN host names only, the value of the
origin
property is not consistently Unicode or punycode; for greatest compatibility check for both the IDN and punycode values when using this property if you expect messages from IDN sites. This value will eventually be consistently IDN, but for now you should handle both IDN and punycode forms.
值对于
origin
property when the sending window contains a
javascript:
or
data:
URL is the origin of the script that loaded the URL.
window.postMessage
is available to JavaScript running in chrome code (e.g., in extensions and privileged code), but the
source
property of the dispatched event is always
null
as a security restriction. (The other properties have their expected values.)
It is not possible for content or web context scripts to specify a
targetOrigin
to communicate directly with an extension (either the background script or a content script). Web or content scripts
can
使用
window.postMessage
采用
targetOrigin
of
"*"
to broadcast to every listener, but this is discouraged, since an extension cannot be certain the origin of such messages, and other listeners (including those you do not control) can listen in.
Content scripts should use runtime.sendMessage to communicate with the background script. Web context scripts can use custom events to communicate with content scripts (with randomly generated event names, if needed, to prevent snooping from the guest page).
Lastly, posting a message to a page at a
文件:
URL currently requires that the
targetOrigin
argument be
"*"
.
file://
cannot be used as a security restriction; this restriction may be modified in the future.
| 规范 | 状态 | 注释 |
|---|---|---|
|
HTML 实时标准
The definition of 'postMessage()' in that specification. |
实时标准 |
| 桌面 | 移动 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
postMessage
|
Chrome 1 | Edge 12 |
Firefox
8
|
IE
10
|
Opera 9.5 | Safari 4 | WebView Android 1 | Chrome Android 18 |
Firefox Android
8
|
Opera Android 10.1 | Safari iOS 3.2 | Samsung Internet Android 1.0 |
transfer
argument
|
Chrome ? | Edge 12 | Firefox 20 | IE Yes | Opera ? | Safari ? | WebView Android ? | Chrome Android ? | Firefox Android 20 | Opera Android ? | Safari iOS ? | Samsung Internet Android ? |
完整支持
兼容性未知
见实现注意事项。
Window
applicationCache
caches
closed
console
controllers
crossOriginIsolated
crypto
customElements
defaultStatus
devicePixelRatio
dialogArguments
目录
document
event
frameElement
frames
fullScreen
history
indexedDB
innerHeight
innerWidth
isSecureContext
isSecureContext
length
localStorage
location
locationbar
menubar
mozAnimationStartTime
mozInnerScreenX
mozInnerScreenY
mozPaintCount
名称
navigator
onabort
onafterprint
onanimationcancel
onanimationend
onanimationiteration
onappinstalled
onauxclick
onbeforeinstallprompt
onbeforeprint
onbeforeunload
onblur
oncancel
oncanplay
oncanplaythrough
onchange
onclick
onclose
oncontextmenu
oncuechange
ondblclick
ondevicelight
ondevicemotion
ondeviceorientation
ondeviceorientationabsolute
ondeviceproximity
ondragdrop
ondurationchange
onended
onerror
onfocus
onformdata
ongamepadconnected
ongamepaddisconnected
ongotpointercapture
onhashchange
oninput
oninvalid
onkeydown
onkeypress
onkeyup
onlanguagechange
onload
onloadeddata
onloadedmetadata
onloadend
onloadstart
onlostpointercapture
onmessage
onmessageerror
onmousedown
onmouseenter
onmouseleave
onmousemove
onmouseout
onmouseover
onmouseup
onmozbeforepaint
onpaint
onpause
onplay
onplaying
onpointercancel
onpointerdown
onpointerenter
onpointerleave
onpointermove
onpointerout
onpointerover
onpointerup
onpopstate
onrejectionhandled
onreset
onresize
onscroll
onselect
onselectionchange
onselectstart
onstorage
onsubmit
ontouchcancel
ontouchstart
ontransitioncancel
ontransitionend
onunhandledrejection
onunload
onuserproximity
onvrdisplayactivate
onvrdisplayblur
onvrdisplayconnect
onvrdisplaydeactivate
onvrdisplaydisconnect
onvrdisplayfocus
onvrdisplaypointerrestricted
onvrdisplaypointerunrestricted
onvrdisplaypresentchange
onwheel
opener
origin
outerHeight
outerWidth
pageXOffset
pageYOffset
parent
性能
personalbar
pkcs11
screen
screenLeft
screenTop
screenX
screenY
scrollbars
scrollMaxX
scrollMaxY
scrollX
scrollY
self
sessionStorage
sidebar
speechSynthesis
status
statusbar
toolbar
top
visualViewport
window
alert()
atob()
back()
blur()
btoa()
cancelAnimationFrame()
cancelIdleCallback()
captureEvents()
clearImmediate()
clearInterval()
clearTimeout()
close()
confirm()
convertPointFromNodeToPage()
convertPointFromPageToNode
createImageBitmap()
dump()
fetch()
find()
focus()
forward()
getAttention()
getComputedStyle()
getDefaultComputedStyle()
getSelection()
home()
matchMedia()
minimize()
moveBy()
moveTo()
open()
openDialog()
postMessage()
print()
prompt()
queueMicrotask()
releaseEvents()
requestAnimationFrame()
requestFileSystem()
requestIdleCallback()
resizeBy()
resizeTo()
restore()
routeEvent()
scroll()
scrollBy()
scrollByLines()
scrollByPages()
scrollTo()
setCursor()
setImmediate()
setInterval()
setTimeout()
showModalDialog()
sizeToContent()
stop()
updateCommands()
event
afterprint
animationcancel
animationend
animationiteration
beforeprint
beforeunload
blur
copy
cut
DOMContentLoaded
error
focus
hashchange
languagechange
load
message
messageerror
offline
online
orientationchange
pagehide
pageshow
paste
popstate
rejectionhandled
storage
transitioncancel
unhandledrejection
unload
vrdisplayconnect
vrdisplaydisconnect
vrdisplaypresentchange
BeforeUnloadEvent
DOMStringMap
ErrorEvent
GlobalEventHandlers
HTMLAnchorElement
HTMLAreaElement
HTMLAudioElement
HTMLBRElement
HTMLBaseElement
HTMLBaseFontElement
HTMLBodyElement
HTMLButtonElement
HTMLCanvasElement
HTMLContentElement
HTMLDListElement
HTMLDataElement
HTMLDataListElement
HTMLDialogElement
HTMLDivElement
HTMLDocument
HTMLElement
HTMLEmbedElement
HTMLFieldSetElement
HTMLFormControlsCollection
HTMLFormElement
HTMLFrameSetElement
HTMLHRElement
HTMLHeadElement
HTMLHeadingElement
HTMLHtmlElement
HTMLIFrameElement
HTMLImageElement
HTMLInputElement
HTMLIsIndexElement
HTMLKeygenElement
HTMLLIElement
HTMLLabelElement
HTMLLegendElement
HTMLLinkElement
HTMLMapElement
HTMLMediaElement
HTMLMetaElement
HTMLMeterElement
HTMLModElement
HTMLOListElement
HTMLObjectElement
HTMLOptGroupElement
HTMLOptionElement
HTMLOptionsCollection
HTMLOutputElement
HTMLParagraphElement
HTMLParamElement
HTMLPictureElement
HTMLPreElement
HTMLProgressElement
HTMLQuoteElement
HTMLScriptElement
HTMLSelectElement
HTMLShadowElement
HTMLSourceElement
HTMLSpanElement
HTMLStyleElement
HTMLTableCaptionElement
HTMLTableCellElement
HTMLTableColElement
HTMLTableDataCellElement
HTMLTableElement
HTMLTableHeaderCellElement
HTMLTableRowElement
HTMLTableSectionElement
HTMLTemplateElement
HTMLTextAreaElement
HTMLTimeElement
HTMLTitleElement
HTMLTrackElement
HTMLUListElement
HTMLUnknownElement
HTMLVideoElement
HashChangeEvent
历史
ImageData
定位
MessageChannel
MessageEvent
MessagePort
Navigator
NavigatorGeolocation
NavigatorID
NavigatorLanguage
NavigatorOnLine
NavigatorPlugins
PageTransitionEvent
Plugin
PluginArray
PopStateEvent
PortCollection
PromiseRejectionEvent
RadioNodeList
Transferable
ValidityState
WindowBase64
WindowEventHandlers
WindowTimers