iframe+postMessage实现跨域通信

前言

需求背景:

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

实现思路:

  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页面

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Puppeteer学习

一步一步学习Vue(十一)

1662
来自专栏张戈的专栏

原创插件:WordPress博客友好对话框+文章随机推荐滚动条插件(附代码版)

双 11 光棍节,我在博客发布了一篇给博客部署一个友好对话框的教程,用了几天感觉非常不错!就进一步折腾了一下,目前这个 js 已实现以下多种功能: 一、功能描述...

48112
来自专栏有趣的django

一个完整的Django入门指南(二)

第三部分 Introduction        In this tutorial, we are going to dive deep into two f...

6707
来自专栏数据小魔方

R语言笔记之——常用数据导入方式简介

因为之前旁听过几节R语言的课程,再加上自己练习数据可视化的需要(特别是可视化包——“ggplot2”),学了些R语言的皮毛。 总觉得基础没打牢,好高骛远、急于求...

3257
来自专栏王磊的博客

jQuery.html()方法ie下不能设置html代码的问题

jQuery一般来说还是很好用的,但有时候它也会有些问题的,比如jQuery的html()方法设置html代码,在一种情况下,ie6、ie7、ie8 下是不能...

38011
来自专栏web开发

前后端分离跨服务器文件上传-Java SpringMVC版

 近来工作上不上特别忙,加上对后台java了解一点,所以就抽时间,写了一个java版本的前后端分离的跨服务器文件上传功能,包括前后端代码。 一、Tomcat服务...

3K8
来自专栏macOS 开发学习

一步一步,开始上手Mac 开发(一)

通过本文,你可以创建你的第一个Mac Application,编译并指定版本号,而且经过练习,你应该掌握:

2103
来自专栏快乐八哥

Windows8异步编程的注意事项

Windows8 App开发中涉及到下载数据和上传数据。针对小的数据使用的是WinJS.xhr(),而针对大的文件,不方便使用post方式直接上传的文件都使用B...

20910
来自专栏编程之旅

PHP开发——yii2多图上传组件的使用

最近在使用yii2开发一个表单页面的时候,有多图上传的需求,稍微找了找这方面的组件,基本都安利fileInput这个组件,于是就尝试着使用这个库来完成后端表单页...

2731
来自专栏河湾欢儿的专栏

vue keep-alive

结合router,缓存部分页面 使用$route.meta的keepAlive属性:

2303

扫码关注云+社区

领取腾讯云代金券