前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iframe+postMessage实现跨域通信

iframe+postMessage实现跨域通信

作者头像
pitaojin
发布2018-05-25 16:52:30
5.2K1
发布2018-05-25 16:52:30
举报

前言

需求背景:

最近开发管理系统,需要在本页面跳转到一个图片管理系统上传图片,上传成功后返回图片链接,然后返回管理系统,显示图片

实现思路:

  1. 上传图片时,需要在本窗口跳转到图片管理系统,并且两个系统之间要通信
  2. 考虑到两个系统是不同的端口号,存在跨域问题,这时发现HTML5新增了一个API-window.postMessage(),于是就决定用iframe结合window.postMessage()实现
  3. 在页面中嵌入一个iframe,将图片管理系统嵌入到当前的管理系统中,结合window.postMessage()实现跨域通信

项目背景

  • 该管理系统基于React.js搭建,在此简称为A页面,地址为http://www.blogoog.com:8000
  • 图片管理系统基于Vue.js搭建,在此简称为B页面,地址为http://www.blogoog.com:8088

具体实现

参考资料

1、A页面使用到的语法

window.postMessage()

otherWindow.postMessage(message, targetOrigin, [transfer]);

  • otherWindow:其他窗口的一个引用(在这里我使用了iframe的contentWindow属性)
  • message:将要发送到其他window的数据(可以不受限制的将数据对象安全的传送给目标窗口而无需自己序列化,原因是因为采用了结构化克隆算法:https://developer.mozilla.org/zh-CN/docs/Web/Guide/API/DOM/The_structured_clone_algorithm
  • targetOrigin:接收信息的URL(在这里我当然填的B页面的URL)
  • transfer:可选参数(在这里我没使用)

具体参考:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage

window.addEventListener('message', receiveMessage, false);

target.addEventListener(type, listener, options);

  • type:表示监听事件类型的字符串
  • listener:当所监听的事件类型触发时,会通知的一个对象或者一个函数
  • potions:可选参数(在此我用false,表示在listener被调用之后不会自动移除)

具体参考:https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener

receiveMessage = (event) => {}
  • event.data:从另一个window传递过来的对象(包含传递过来的所有信息)
  • event.origin||event.originalEvent.origin:window.postMessage()发送消息的目标URL
  • event.source:对发送消息的窗口对象的引用

注意点!!!

  • 在页面内嵌入iframe页面的情况下,需要等到页面内的iframe页面,也就是B页面加载完成之后,才能进行postMessage跨域通信
  • event.origin中的origin不能保证是该窗口的当前origin或者未来origin,因为postMessage被调用后,可能会被导航到不同的位置,所以需要做个异常情况判断处理origin !== 'http://www.blogoog.com:8088'

2、B页面使用到的语法

top.postMessage('data', 'http://www.blogoog.com:8000')
  • 参考上面A页面的语法
  • 为什么用top而不用window下面再讲
window.addEventListener('message', receiveMessage, false);
  • 参考上面A页面的语法
receiveMessage = (event) => {}
  • 参考上面A页面的语法

window.postMessage()中的window到底是啥?

始终是你需要通信的目标窗口

  • A页面中:A页面向B页面发送跨域信息,window就是在A页面中嵌入的iframe指向的B页面的window,即:iframe.contentWindow
  • B页面中:B页面想A页面发送跨域信息,window就是A页面的window,在这里因为B页面时嵌入到A页面中的,对于B页面来讲,window就是top或者parent

需要特别注意的坑

  1. 一定要等A页面嵌入的B页面加载完成之后,再进行postMessage跨域通信
  2. 一定要对origin做判断,去掉不是来自我们目标窗口的origin,防止来自其他origin的攻击
  3. 着重注意window.postMessage()中window的用法,明确目标窗口的window

献上代码

A页面

B页面

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.05.16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
    • 需求背景:
      • 实现思路:
        • 项目背景
        • 具体实现
          • 参考资料
            • 1、A页面使用到的语法
              • window.postMessage()
              • window.addEventListener('message', receiveMessage, false);
              • receiveMessage = (event) => {}
            • 注意点!!!
              • 2、B页面使用到的语法
                • top.postMessage('data', 'http://www.blogoog.com:8000')
                • window.addEventListener('message', receiveMessage, false);
                • receiveMessage = (event) => {}
              • window.postMessage()中的window到底是啥?
              • 需要特别注意的坑
              • 献上代码
                • A页面
                  • B页面
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档