必须用 postmessage 通信,严禁直接调用或访问 dom;需监听 iframe.onload 后再发消息,确保 contentwindow 可用且 sandbox 允许脚本;targetorigin 必须精确指定,禁用 '*';回传用 event.origin;握手需带 nonce 和 type,后续消息携带 pluginid 并校验类型与字段。

必须用 postMessage,不能直接调用函数或访问 DOM;编辑器和宿主页面必然跨源,浏览器会直接抛 SecurityError 阻断任何尝试——这不是兼容性问题,是同源策略的强制拦截。
iframe 加载完成前发消息必丢,且不报错
常见错误是给 iframe.src 赋值后立刻调用 iframe.contentWindow.postMessage()。此时 contentWindow 可能为 null,或子页面尚未解析完,消息被浏览器静默丢弃。
- 必须监听
iframe.onload(比DOMContentLoaded更可靠),再取contentWindow - 若 iframe 含
sandbox属性,且未声明allow-scripts,contentWindow也会不可访问 - 不要用
setTimeout“等几秒”来赌加载完成——移动端、弱网、CDN 缓存都可能导致时序漂移
targetOrigin 写成 '*' 就等于没设防
开发时图省事写 '*',上线后等于把编辑器控制权暴露给任意嵌入方。攻击者只需在恶意页面里放一个同名 iframe,就能伪造指令触发敏感操作(如导出用户数据、执行插件脚本)。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 生产环境
targetOrigin必须精确到协议+域名+端口,例如'https://editor.example.com:8080' - 如果宿主页面是
https,而编辑器 iframe 是http,消息会被浏览器静默丢弃(协议不一致) - 回传时用
event.source.postMessage(data, event.origin),而不是硬编码 origin——event.origin才是真实可信来源
握手阶段不带 nonce 和 type 字段,后续通信无法隔离上下文
编辑器可能同时加载多个第三方插件(如公式、图表、代码块),若所有消息都走同一个 message 监听器且无标识,就无法区分哪条指令该由哪个插件处理,极易串扰或误执行。
- 首次通信应为双向握手:
editor发{ type: 'handshake:challenge', nonce: 'xyz789' },插件回{ type: 'handshake:response', nonce: 'xyz789', pluginId: 'chart-v3' } - 后续每条消息都必须携带
pluginId字段,编辑器按此路由到对应插件逻辑 -
nonce用于防重放,不能复用;超时(如 3s)未收到响应,应标记该插件加载失败并禁用其功能 - 禁止在握手消息中传
function、Date、RegExp或 DOM 节点——结构化克隆会静默转为空对象,导致nonce或pluginId丢失
消息体缺少类型约束和字段校验,运行时容易崩
传 { cmd: 'insert', html: '<script>…' }</script> 这类松散结构,半年后维护时连自己都难定位字段含义;更危险的是,若宿主传 html: null 或 html: {},编辑器直接插入会导致 XSS 或白屏。
- 统一用
type字段做动作路由:'editor:insert-html'、'plugin:sync-config'、'editor:export-json' - 每个
type对应明确 payload 约束:比如editor:insert-html只接受html: string,且需在接收端做typeof data.html === 'string'校验 - 监听器开头加基础防护:
if (typeof event.data !== 'object' || !('type' in event.data)) return - 不要依赖
event.source做权限判断——它可被伪造;权限只认event.origin+ 握手成功的pluginId
最常被跳过的一步是:没有为每条需要响应的消息设计唯一 id 并配超时清理。编辑器发了 { type: 'get-selection', id: 'req_abc' },插件回传时带上相同 id,但编辑器若不主动维护 pending 请求队列并 clearTimeout,就永远不知道这条请求是否失效或已被忽略。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










