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

iframe实战:跨域通信与安全隔离

iframe

  • iframe是什么
  • 应用场景
  • 通信方式
    • 同源
    • 跨域
  • 视频演示
    • 代码部分
    • iframe子页面代码

iframe是什么

  • <iframe> 是 HTML 提供的“页中页”标签,它能在当前文档内嵌入一个独立的浏览上下文,拥有自己完整的 window、DOM、CSS 和 JavaScript 运行环境,天然与父页面隔离;借助 postMessage、sandbox、allow 等 API 与安全属性,开发者既可在跨域场景下安全地通信与限制权限,又能通过懒加载、预连接等手段优化性能,因此常被用于第三方内容嵌入、微前端子应用、支付收银台、在线文档预览等需要“隔离 + 互动”的业务场景。

应用场景

  • iframe 把“独立页”嵌入主文档,天然隔离又支持 postMessage 通信,因此常用来加载第三方支付页、微前端子应用、跨域上传组件、在线文档预览、广告或地图等需要安全沙箱、样式隔离、懒加载的模块,既避免脚本冲突,又能随取随用、按需销毁。

通信方式

同源

  • 父页面和 iframe 的源(协议 + 域名 + 端口)完全相同,因此浏览器允许它们直接互相访问对方的 document、window 和 DOM 节点,无需任何消息转发或 postMessage。
    例如下面代码块
// 父页拿到子页的 document
const childDoc = window.frames[0].document;
childDoc.body.style.background = '#000';   // 直接改样式// 子页拿到父页的 DOM
window.parent.document.getElementById('header').innerText = 'Hi from iframe';

跨域

  • 使用PostMessage进行跨域通信
  1. 双方先 window.addEventListener(‘message’, handler) 注册监听器;
  2. 发消息用 otherWindow.postMessage(data, origin),data 最好是结构化克隆对象,origin 必须精确匹配,避免 “*”;
    例如下列代码块:
 if (window.parent !== window) {// 发送数据到父页面window.parent.postMessage({type: 'mock_data',data: mockData,source: 'iframe'}, '*'); // 第二个参数是目标origin,'*'表示任何originconsole.log('数据已发送到父页面:', mockData);alert('数据已成功发送到父页面!');} else {alert('当前页面不是iframe,无法发送数据到父页面');}

视频演示

  • 下面这两个网页实现了一个iframe父子页面通信的演示系统。子页面(iframe.html)负责生成包含用户名、用户ID、消息内容和时间戳的模拟数据,并通过点击"发送数据到父页面"按钮,使用postMessage API将数据发送给父页面。父页面(parent.html)则通过监听message事件来接收来自子页面的数据,并以美观的卡片形式在页面上方展示接收到的用户信息、消息内容和时间戳,实现了跨域iframe之间的安全数据通信功能。
    在这里插入图片描述

代码部分

  • 父页面代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>iframe父页面</title></head><style>#parent {background-color: aqua;}iframe {width: 80vw;height: 80vh;}</style><body><div id="parent"><h1>这是父页面</h1><div id="received-data">等待接收数据...</div><iframe src="iframe.html" frameborder="0"></iframe></div></body><script>// 接收来自iframe的消息window.addEventListener("message", function (event) {// 验证消息来源(可选,但推荐)// if (event.origin !== '期望的origin') return;const data = event.data;// 检查消息类型if (data.type === "mock_data" && data.source === "iframe") {console.log("父页面收到数据:", data.data);// 显示接收到的数据displayReceivedData(data.data);}});// 显示接收到的数据function displayReceivedData(mockData) {const container = document.getElementById("received-data");let html = "<h3>从子页面接收到的Mock数据:</h3>";mockData.forEach((item, index) => {html += `<div class="received-message"><strong>消息 ${index + 1}:</strong><br><strong>用户:</strong> ${item.userName} (ID: ${item.userId})<br><strong>消息内容:</strong> ${item.message}<br><strong>时间:</strong> ${item.timestamp}</div>`;});html += `<div class="data-info">共收到 ${mockData.length} 条消息</div>`;container.innerHTML = html;// 滚动到最新数据container.scrollTop = container.scrollHeight;}</script>
</html>

iframe子页面代码

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>iframe子页面</title></head><style>#iframe {background-color: rgb(255, 204, 0);width: 80vw;height: 80vh;}</style><body><div id="iframe"><h1>这是子页面</h1><div id="messages-container"></div><button id="send-btn">发送</button></div></body><script>// Mock数据生成函数function generateMockData() {const users = [{ id: 1001, name: "张三" },{ id: 1002, name: "李四" },{ id: 1003, name: "王五" },{ id: 1004, name: "赵六" },{ id: 1005, name: "钱七" },];const messages = ["你好,今天天气不错!","这个功能看起来很棒!","我同意你的观点","有什么新的更新吗?","感谢分享这些信息","期待下次的会议","这个设计很漂亮","代码运行得很顺利","需要帮忙吗?","完成得很棒!",];const mockData = [];// 生成10条模拟消息for (let i = 0; i < 10; i++) {const randomUser = users[Math.floor(Math.random() * users.length)];const randomMessage =messages[Math.floor(Math.random() * messages.length)];// 生成随机时间戳(最近7天内)const randomDaysAgo = Math.floor(Math.random() * 7);const randomHoursAgo = Math.floor(Math.random() * 24);const randomMinutesAgo = Math.floor(Math.random() * 60);const timestamp = new Date();timestamp.setDate(timestamp.getDate() - randomDaysAgo);timestamp.setHours(timestamp.getHours() - randomHoursAgo);timestamp.setMinutes(timestamp.getMinutes() - randomMinutesAgo);mockData.push({userId: randomUser.id,userName: randomUser.name,message: randomMessage,timestamp: timestamp.toLocaleString("zh-CN"),});}return mockData;}// 显示mock数据function displayMockData() {const container = document.getElementById('messages-container');const mockData = generateMockData();mockData.forEach(data => {const messageDiv = document.createElement('div');messageDiv.className = 'message';messageDiv.innerHTML = `<div><span class="user-info">${data.userName} (ID: ${data.userId})</span><span class="timestamp">${data.timestamp}</span></div><div class="message-content">${data.message}</div>`;container.appendChild(messageDiv);});}// 通过postMessage发送数据到父页面function sendDataToParent() {const mockData = generateMockData();// 获取当前iframe的window.parent(父窗口)if (window.parent !== window) {// 发送数据到父页面window.parent.postMessage({type: 'mock_data',data: mockData,source: 'iframe'}, '*'); // 第二个参数是目标origin,'*'表示任何originconsole.log('数据已发送到父页面:', mockData);alert('数据已成功发送到父页面!');} else {alert('当前页面不是iframe,无法发送数据到父页面');}}// 页面加载完成后显示数据document.addEventListener('DOMContentLoaded', displayMockData);// 设置发送按钮点击事件const sendButton = document.getElementById('send-btn');sendButton.addEventListener('click', sendDataToParent);</script></script>
</html>
http://www.dtcms.com/a/498968.html

相关文章:

  • 购物网站的建设意义html可视化编辑软件
  • Bootstrap 字体图标
  • PVE 9.0 定制 Debian 13 镜像 支持 Cloud-Init 快速部署虚拟机【模板篇】
  • 长春建站模板搭建高端品牌包包都有哪些
  • ai周公解梦抖音快手微信小程序看广告流量主开源
  • 【无标题】大模型-高效优化技术全景解析:微调 量化 剪枝 梯度裁剪与蒸馏 下
  • 自动化信息交付:深度解析AI驱动的每日简报系统架构与实现
  • 做微信公众号第三网站男女做视频观看网站
  • 定时任务Quartz原理详解
  • Rethinking SSIM-Based Optimization in Neural Field Training
  • rocketmq和kafka的区别之顺序消费
  • 套路有*道龙激光-乐多刀销*游戏程序系统方案
  • Angular 2 数据显示
  • 如何快速做单页面网站怎么查网站建设是哪家公司
  • 外国网站备案网站板块设置
  • 从 ClickHouse 到 StarRocks 存算分离: 携程 UBT 架构升级实践
  • 云手机 三角洲行动跑刀
  • Java 反射机制深度解析:从对象创建到私有成员操作
  • c++|表达最值的更好方法|clamp
  • Altium Designer(AD24)File文件功能总结
  • 【EE初阶 - 网络原理】应用层协议(下)
  • Pyinstaller - Python桌面应用打包的首选工具
  • PHP编程语言选择
  • 太原市做网站专业团队广告语
  • 桂林设计单位资质升级网站手机怎么建网站
  • k8s问题详解1:k8s集群上传文件过大导致413 Request Entity Too Large(请求文件实体过大)
  • 计算机毕业设计:Python农业数据可视化分析系统 气象数据 农业生产 粮食数据 播种数据 爬虫 Django框架 天气数据 降水量(源码+文档)✅
  • 怎么做一个链接网站东莞直播app软件开发定制
  • VSCode - 设置MSYS2终端
  • MATLAB学习文档(二十五)