当前位置: 首页 > news >正文

前端跨域解决方案(4):postMessage

1 postMessage 核心

postMessage 是现代浏览器提供的跨域通信标准 API,允许不同源的窗口(如主页面与 iframe、弹出窗口、Web Worker)安全交换数据。相比其他跨域方案,它的核心优势在于:

  1. 双向通信能力:支持消息的发送与接收,形成完整的通信闭环

  2. 安全可控性:通过targetOriginevent.origin严格校验消息源,防止恶意攻击

  3. 跨场景兼容性:适用于 iframe 嵌套、多标签页同步、Web Worker 等多种场景

  4. 数据灵活性:支持对象、数组、Blob 等复杂数据类型(基于结构化克隆算法)

1.1 核心 API

1.1.1 发送消息安全传递数据到目标窗口

otherWindow.postMessage(message, targetOrigin);

参数

描述

otherWindow

目标窗口引用,可通过以下方式获取:
・iframe 的 contentWindow
• window.open() 返回的窗口
• window.parent(子窗口访问父窗口)

message

要发送的数据,支持 结构化克隆算法(可包含对象、数组、Blob 等,但需避免函数、DOM 节点)。

targetOrigin

严格限制接收方的源(格式:protocol://domain:port),防止消息被恶意窗口截获。
建议:始终使用具体域名(如 https://trusted.com),避免使用 *

示例:父窗口向 iframe 发送配置数据

// 父窗口代码
const iframe = document.getElementById('myIframe');
iframe.contentWindow.postMessage({ type: 'init', config: { theme: 'dark' } },'https://child-domain.com' // 严格指定iframe的域名
);

1.1.2 接收消息监听并处理跨域数据

window.addEventListener('message', (event) => {const { data, origin, source } = event;// 1. 校验消息来源(安全关键)if (origin !== 'https://trusted.com') {console.warn('未知来源的消息:', origin);return;}// 2. 处理消息数据(根据约定的格式)switch (data.type) {case 'login':console.log('用户登录信息:', data.user);break;case 'logout':// 执行登出逻辑break;}// 3. 可选:回复消息(通过source窗口)source.postMessage({ status: 'received' }, origin);
});
属性描述
event.data发送方传递的数据(类型与发送时一致)。
event.origin发送方的源(如 https://sender.com),用于安全校验。
event.source发送方的窗口引用,可用于回复消息(调用 source.postMessage())。

2 实战案例

2.1 服务端A(servera.js)

// 引入Express框架,这是一个基于Node.js的快速、灵活的Web应用框架
const express = require('express');
// 创建一个Express应用实例,用于处理HTTP请求和响应
const app = express();
// 配置Express应用使用静态文件中间件,指定从'public'文件夹中提供静态资源(如HTML、CSS、图片等)
app.use(express.static('public'));
// 定义应用监听的端口号,3000是前端开发中常用的非特权端口
const port = 3000;
// 启动服务器并监听指定端口,当服务器成功启动后执行回调函数
app.listen(port, () => {// 在控制台输出服务器运行的地址信息,方便开发者确认服务启动状态console.log(`Server is running on http://localhost:${port}`);
});

2.2 静态页面A(a.html)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>a</title>
</head>
<body><!-- 插入id为"b-iframe"的iframe元素,指向http://localhost:4000/b.htmlonload事件在iframe资源加载完成后触发handleIframeLoad函数 --><iframe id="b-iframe" src="http://localhost:4000/b.html" onload="handleIframeLoad()"></iframe><script>// 定义目标源,与iframe的源保持一致,用于postMessage安全校验const targetOrigin = 'http://localhost:4000';// iframe加载完成后的处理函数function handleIframeLoad() {// 通过contentWindow获取iframe的window对象,用于跨窗口通信let bWindow = document.getElementById('b-iframe').contentWindow;// 向iframe发送消息,第二个参数指定目标源防止恶意窗口接收bWindow.postMessage('hello', targetOrigin);}// 监听当前窗口的message事件,接收来自其他窗口的跨域消息window.addEventListener('message', function(event) {// 输出接收到的消息内容(包含event.data、event.origin等安全信息)console.log('Received message: ', event.data);}, false);</script>
</body>
</html>

2.3 服务端B(serverb.js)

// 引入Express框架(基于Node.js的Web应用开发框架,提供路由、中间件等功能)
const express = require('express');
// 创建Express应用实例(核心对象,用于处理HTTP请求和响应)
const app = express();
// 配置静态资源中间件(指定从'public'文件夹中读取HTML、CSS、图片等静态文件)
app.use(express.static('public'));
// 定义服务器监听的端口号(4000为自定义端口,需确保未被其他服务占用)
const port = 4000;
// 启动服务器并绑定端口(回调函数在服务启动成功后执行)
app.listen(port, () => {// 控制台输出服务运行地址(便于开发者确认服务状态和访问路径)console.log(`Server is running on http://localhost:${port}`);
});

2.4 静态页面B(b.html)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>b</title>
</head>
<body><script>// 监听当前窗口的message事件,用于接收其他窗口发送的跨域消息window.addEventListener('message', function(event) {// 输出消息发送方的window对象(可用于回复消息)console.log(event.source); // Window // 输出消息发送方的源(协议+域名+端口),用于安全校验console.log(event.origin); // http://localhost:3000// 向消息发送方返回响应消息,第二个参数指定目标源为发送方的源event.source.postMessage('world', event.origin);}, false);</script>
</body>
</html>

3 适用场景

场景类型

典型应用案例

微前端架构

主应用与子应用通过 iframe 嵌套,使用 postMessage 传递路由、状态等信息

多标签页同步

电商网站中,用户在 A 标签页添加商品,B 标签页实时更新购物车数量

Web Worker 通信

主线程与 Web Worker 通过 postMessage 交换计算任务和结果

跨域文件操作

本地文件选择器页面与主应用通过 postMessage 传递 File 对象

postMessage 作为浏览器原生跨域方案,通过 “消息订阅 - 发布” 模式实现了安全可控的跨窗口通信。在实际应用中,结合 Web Worker、Service Worker 等技术,可构建更复杂的跨域应用架构。如需处理高频实时通信(如在线协作、游戏),可结合 WebSocket 方案;对于服务端跨域需求,CORS 与代理服务器仍是主流选择。

通过合理设计消息协议与安全策略,postMessage 能在保证用户数据安全的前提下,高效解决前端开发中的跨域通信难题。

下一章将介绍 websocket 方案 ,敬请期待!

http://www.xdnf.cn/news/1058725.html

相关文章:

  • 剑指offer32_二叉搜索树的后序遍历序列
  • 新发布的一款使用ReactNative新架构加载Svga动画的开源插件[android/ios]
  • 数据结构——选择题—查漏补缺
  • 【unitrix】 3.0 基本结构体(types.rs)
  • 二、OpenCV的第一个程序
  • Uniapp H5端SEO优化全攻略:提升搜索引擎排名与流量
  • 结合 STM32CubeMX 使用 FreeRTOS 实时操作系统
  • 【ClipPal】推荐一个非常好用的粘贴板记录工具
  • 侧信道分析中的简单模板攻击(TA)Python实现(带测试)
  • 【web应用】Vue 3 中实现 Chart.js 折线图:详细指南与最佳实践
  • 14.2 《3小时从零搭建企业级LLaMA3语言助手:GitHub配置+私有化模型集成全实战》
  • 基于CNN的FashionMNIST数据集识别6——DenseNet模型
  • 基于深度学习的智能文本摘要系统:技术与实践
  • Uniapp性能优化全面指南:从原理到实践
  • GNU Octave 基础教程(1):在 Ubuntu 22.04 和 Windows 11 上的安装指南
  • 【Linux】UDP与TCP协议
  • 电路图识图基础知识-普通卧式镗床识图(三十)
  • 深度体验KingbaseES在线平台:从零掌握企业级数据库实战(附架构图+代码案例)
  • Python基础学习框架(总周期:8周)
  • 九日集训第六天
  • 1572. 矩阵对角线元素的和
  • 计算机网络学习笔记:TCP流控、拥塞控制
  • 大模型知识库RAG框架,比如LangChain、ChatChat、FastGPT等等,哪个效果比较好
  • 前端开发面试题总结-vue2框架篇(三)
  • 安装谷歌vue开发工具插件devtools支持vue2
  • CentOS7 安装最新版 Docker
  • 【RocketMQ 生产者和消费者】- 消费者重平衡(1)
  • 《开窍》读书笔记9
  • 为什么要进行行为验证,行为验证方式有哪些?
  • 什么是数据清洗?数据清洗有哪些步骤?