18

使用 window.postMessage() 时,我无法捕捉错误。

我希望能够捕捉到我得到的错误 -

“无法向http://www.that-domain.com发布消息。收件人的来源为http://www.this-domain.com

简单的示例代码(应该错误):

 try {
    window.postMessage('1','http://www.differentDomain.com');
 } 
 catch (e) {       
     alert('error');
 }

更详细的流程:我正在使用 jQuery 将跨域 iframe 添加到文档中,然后发布到它。这不应该出错,因为目标来源应该匹配 - 它们都由 proxyDomain 变量设置。

var $iframeProxy = $('<iframe id="myIFrame" src="' + proxyDomain + '"></iframe>').appendTo('body');

window.storageProxy = $iframeProxy[0].contentWindow;

try {
    window.storageProxy.postMessage(message, proxyDomain);
}
catch (e) {       
    alert('error');
}
4

3 回答 3

7

无法捕获错误,但通常如果目标来源不同,则会发生错误,情况是测试与生产场景。

因此,您可以检查什么是父域并相应地更改目标来源:

function getTargetOrigin()
{
    try {
        var url = (window.location != window.parent.location) ? document.referrer : document.location.href;
        if (url.indexOf('www.myproduction-website.com')!=-1)
            return document.location.protocol + '//www.myproduction-website.com'
        else //set the alternative target
            return document.location.protocol + '//' + url.split('/')[2];
    }
    catch(e) //falback to production
    {
        return document.location.protocol + '//www.myproduction-website.com'
    }
}

并在 postMessage 函数中使用它:

function postMessage(message){
    window.top.postMessage( message,getTargetOrigin());
}

使用此解决方案,您可以在多个服务器配置中使用相同的代码,而无需对 targetOrigin url 进行硬编码。

如果您在框架内导航并重新检查 document.referrer,则此解决方案将失败,在这种情况下,它将不包含父 url,而是包含前一个框架 url。在这种情况下,请考虑使用“*”作为 targetOrigin url,这是向其他域发送消息的唯一可行解决方案。

希望能帮助到你!

于 2017-11-15T11:10:57.413 回答
3

看起来 HTML5 规范中概述了如果域来源不匹配,则不会引发错误,并且应该静默中止。

http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#web-messaging

10.4.3 发布消息 - 第 9 部分

“...如果 targetOrigin 参数是绝对 URL,并且调用该方法的 Window 对象的 Document 与 targetOrigin 的来源不同,则静默中止这些步骤。”

于 2013-06-13T06:54:08.327 回答
1

我会添加到matteo-conta's 解决方案提高安全性,以防止虚假域,如www.myproduction-website.com.fakedomain.com接收消息:

function getTargetOrigin() {
    const domainDev = 'mydev-website.com';
    const domainProd = 'myproduction-website.com';
    try {
        var url = (window.location !== window.parent.location) ? document.referrer : document.location.href;
        const domain = url.split('/')[2];
        if (domain.endsWith(domainDev) || domain.endsWith(domainProd))
            return document.location.protocol + domain;
        else return '';
    } catch(e) {
        return ''
    }
}
const targetOrigin = getTargetOrigin();
try{
    if (targetOrigin) window.parent.postMessage(${msg}, targetOrigin);
} catch(e) {
    window.parent.postMessage(e, '*')
}

我还添加了将错误消息发布到任何 targetOrigin 以便您可以使用以下方法在您的网站端捕获它:

window.addEventListener("message", onResponse, false);
onResponse(res) {
    const data = _.get(res, 'data');
    if (res.origin === 'iframe-url-goes-here') {
        console.log('message from iframe', data)
    }
}
于 2020-04-24T14:36:25.353 回答