iframe postMessage传值填充输入框后值清空、日志异常问题咨询
postMessage 传值异常问题排查
现有实现代码
嵌入iframe页面的发送代码
在插入iframe的页面中写入如下代码:
var data = {mails: 'mymail@gmail.com'}; setTimeout( function(){ iframe.postMessage(data,'*'); }, 3000);
父页面的监听代码
父页面(PARENT)中添加如下message事件监听代码:
window.addEventListener('message', function(msg) { jQuery("#iframe-mail_owner").val(msg.data.mails); console.log(msg.data.mails); });

异常现象
代码运行后出现两个不符合预期的问题:
- 目标输入框可被正确填充邮箱值,但1秒后内容就会变为空,经排查是后续有其他postMessage事件触发,传入的mails字段值为undefined
- 控制台日志中出现了reCAPTCHA等其他无关数据,但代码中明确指定仅打印
msg.data.mails字段,而非输出完整的data对象
问题原因
核心问题是message事件监听没有做任何来源校验和数据合法性校验:
- 浏览器的
message事件是全局广播的,页面内所有触发postMessage的行为(包括reCAPTCHA这类第三方组件、其他嵌入的iframe、甚至浏览器插件发送的消息)都会触发绑定的监听回调。现有代码不对消息发送方做校验,也不判断消息结构是否符合预期,只要有消息进来就直接读取msg.data.mails赋值、打印。 - 自己发送的带正确邮箱的消息先触发回调,输入框被填入正确值;后续第三方组件发送的消息里没有
mails字段,读取到的值就是undefined,把undefined赋值给输入框自然会清空原有内容,打印值的时候也会连带带出第三方消息附带的无关数据。 - 另外发送消息时目标源填
*属于不安全写法,会允许任意窗口接收当前发送的消息,存在数据泄露风险。
修复方法
- 监听回调增加两层过滤:
- 来源校验:只处理自己信任域名发来的消息,直接拦截第三方、未知来源的消息
- 数据校验:判断消息数据中确实存在
mails字段,且值为合法字符串,再执行后续赋值、打印操作
- 发送
postMessage时不要用*作为目标源,明确指定接收方的准确域名,避免消息泄露。
修复后的代码参考:
修复后的iframe发送代码
var data = {mails: 'mymail@gmail.com'}; setTimeout( function(){ // 将第二个参数替换为父页面的实际域名,禁止使用* iframe.postMessage(data, 'https://your-real-domain.com'); }, 3000);
修复后的父页面监听代码
// 替换为自身业务的可信域名,本地调试可替换为对应本地服务地址 const TRUSTED_SOURCE_ORIGIN = 'https://your-real-domain.com'; window.addEventListener('message', function(msg) { // 非可信来源直接终止处理 if (msg.origin !== TRUSTED_SOURCE_ORIGIN) return; // 数据结构不符合预期直接终止处理 if (!msg.data || typeof msg.data.mails !== 'string') return; // 校验通过后执行业务逻辑 jQuery("#iframe-mail_owner").val(msg.data.mails); console.log(msg.data.mails); });
内容的提问来源于stack exchange,提问作者Lowlowlow
相关产品推荐
相关产品推荐

