html5 postMessage前端跨域并前端监听的方法示例


Posted in HTML / CSS onNovember 01, 2018

有时候会遇到傻X需求,比如前端单点登陆!遇到需求,就要去想解决办法,

这里我给大家做一个简单的前端单点登陆的解决方案,

用到的就是postMessage跨域信息传输以及onstorage的监听。

本文用到的知识点 koa架设静态资源服务、跨域、postMessage的用法、onstorage监听storage

第一步、架设两个不同端口的服务

我们这里用koa2来搭建两个服务到不同的端口,来模拟一下真正的工作中需要出现的跨域情况。

非常的简单 主要用到 koa-static这个中间件
搭建起来也是非常容易的,如果大家想学node相关的知识 可以加我微信shouzi_1994 或者在博客下面留言你的联系方式 这里就不多说废话了 直接上代码 视频内会有详细的搭建步骤

// localhost:4000
const Koa = require('koa');
const path = require('path')
const static = require('koa-static')
const app = new Koa();

//设置静态资源的路径 
const staticPath = './static'

app.use(static(
    path.join( __dirname,  staticPath)
  ))

  
console.log("服务启动在4000端口")

app.listen(4000);


// localhost:3000
const Koa = require('koa');
const path = require('path')
const static = require('koa-static')
const app = new Koa();

//设置静态资源的路径 
const staticPath = './static'

app.use(static(
    path.join( __dirname,  staticPath)
  ))


console.log("服务启动在4000端口")

app.listen(4000);

第二步、跨域通讯postMessage

我们首先来看一下 postMessage的API

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

otherWindow
其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。

message
将要发送到其他 window的数据。它将会被结构化克隆算法序列化。这意味着你可以不受什么限制的将数据对象安全的传送给目标窗口而无需自己序列化。[1]

targetOrigin
通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串""(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口;例如,当用postMessage传送密码时,这个参数就显得尤为重要,必须保证它的值与这条包含密码的信息的预期接受者的origin属性完全一致,来防止密码被恶意的第三方截获。如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。

transfer 可选
是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

怎么样是不是很容易理解,这里给大家中文化一下。

要传输的那个(父)子窗口.postMessage(传输的内容, 传输到哪个地址, [权限是否转移(一般不用)]);

提前说一下,要想跨域传输,必须是父子页面,也就是说,是通过js Open的页面,或者ifream嵌套的页面

好了 我们开始来写代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
        <!-- postMessage和iframe解决普通的跨域问题 -->
    我是端口3000网站的内容
    <button onclick="send()">发消息给儿子</button>
    
    <iframe style="display:none" src="http://localhost:4000" frameborder="0"></iframe>
<script>
        function send() { 
                window.frames[0].postMessage({a:"1"},"http://localhost:4000"); // 触发跨域子页面的messag事件
        }

    window.addEventListener('message', function(event) {
        console.info('儿子来信了', event);
    }, false);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
        <!-- postMessage和iframe解决普通的跨域问题 -->
    我是端口4000网站的内容
    <button onclick="send()">发消息给爸爸</button>
    
    <iframe style="display:none" src="http://localhost:4000" frameborder="0"></iframe>
<script>
       window.addEventListener("message",function(event){
           console.log("爸爸来信了:", event)
        },false)

      function send() {
        parent.postMessage({a:1}, 'http://localhost:3000'); // 
     }
</script>
</body>
</html>

写到这里我们已经实现了父子页面的跨域通讯,但是这个通讯只发生在一个窗口内啊,并没有达到我想要的效果,该怎么办呢。

监听数值变化,做出及时反应

到这里大家需要思考,什么东西是浏览器上的所有同域名网站都能看到的呢?

没错,storage,我们只需要对这个进行监听就好了。

这里我们选择监听 loacalStorage 现在我们对子页面做一下改进

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
        <!-- postMessage和iframe解决普通的跨域问题 -->
    我是端口4000网站的内容
    <button onclick="send()">发消息给爸爸</button>
    
    <iframe style="display:none" src="http://localhost:4000" frameborder="0"></iframe>
<script>
    
       window.addEventListener("message",function(event){
           console.log("爸爸来信了:", event)
           var data = JSON.stringify(event.data)
           window.localStorage.setItem("data",data)
        },false)

        window.onstorage(function(st){
            console.log(st.key,st.value)
        })
      function send() {
        parent.postMessage({a:1}, 'http://localhost:3000'); // 
     }

</script>

</body>
</html>

看,我们是不是到现在就能够针对跨域传输的内容做出响应了呢?

思考

现在我们做到了两个页面的跨域通讯,那么三个到多个的跨域通讯怎么做呢?其实一个道理啦。现在道理说给你了,写法自己去体验一下吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
CSS3实现鼠标悬停显示扩展内容
Aug 24 HTML / CSS
HTML 5 标签、属性、事件及浏览器兼容性速查表 附打包下载
Oct 20 HTML / CSS
用HTML5实现手机摇一摇的功能的教程
Oct 30 HTML / CSS
HTML5 Web Workers之网站也能多线程的实现
Apr 24 HTML / CSS
浅谈基于HTML5的在线视频播放方案
Feb 18 HTML / CSS
HTML5拖放API实现拖放排序的实例代码
May 11 HTML / CSS
Canvas实现保存图片到本地的示例代码
Jun 28 HTML / CSS
HTML5之消息通知的使用(Web Notification)
Oct 30 HTML / CSS
Html5基于canvas实现电子签名并生成PDF文档
Dec 07 HTML / CSS
奇妙的 CSS shapes(CSS图形)
Apr 05 HTML / CSS
HTML中table表格拆分合并(colspan、rowspan)
Apr 07 HTML / CSS
CSS3 制作的彩虹按钮样式
Apr 11 HTML / CSS
HTML5之消息通知的使用(Web Notification)
Oct 30 #HTML / CSS
详解Html5页面实现下载文件(apk、txt等)的三种方式
Oct 22 #HTML / CSS
html5 http的轮询和Websocket原理
Oct 19 #HTML / CSS
canvas实现扭蛋机动画效果的示例代码
Oct 17 #HTML / CSS
浅谈HTML5中dialog元素尝鲜
Oct 15 #HTML / CSS
canvas进阶之如何画出平滑的曲线
Oct 15 #HTML / CSS
iframe在移动端的缩放的示例代码
Oct 12 #HTML / CSS
You might like
叶罗丽:为什么大家对颜冰这对CP非常关心,却对金茉两人十分冷漠
2020/03/17 国漫
Discuz 模板语句分析及知识技巧
2009/08/21 PHP
PhpMyAdmin中无法导入sql文件的解决办法
2010/01/08 PHP
php cout&amp;lt;&amp;lt;的一点看法
2010/01/24 PHP
PHP获取Exif缩略图的方法
2015/07/13 PHP
PHP结合Mysql数据库实现留言板功能
2016/03/04 PHP
prototype.js的Ajax对象
2006/09/23 Javascript
js模仿windows桌面图标排列算法具体实现(附图)
2013/06/16 Javascript
jquery分割字符串的方法
2015/06/24 Javascript
jQuery实现的漂亮表单效果代码
2015/08/18 Javascript
Nodejs学习item【入门手上】
2016/05/05 NodeJs
浅谈js的url解析函数封装
2016/06/28 Javascript
ThinkJS中如何使用MongoDB的CURD操作
2016/12/13 Javascript
微信小程序倒计时功能实现代码
2017/11/09 Javascript
Node.js net模块功能及事件监听用法分析
2019/01/05 Javascript
js实现随机点名程序
2020/09/17 Javascript
jQuery实现移动端下拉展现新的内容回弹动画
2020/06/24 jQuery
JS如何实现封装列表右滑动删除收藏按钮
2020/07/23 Javascript
vue.js click点击事件获取当前元素对象的操作
2020/08/07 Javascript
为什么推荐使用JSX开发Vue3
2020/12/28 Vue.js
[01:00:35]2018DOTA2亚洲邀请赛3月30日B组 EffcetVSMineski
2018/03/31 DOTA
python计算N天之后日期的方法
2015/03/31 Python
对python中的try、except、finally 执行顺序详解
2019/02/18 Python
利用selenium爬虫抓取数据的基础教程
2019/06/10 Python
python采集百度搜索结果带有特定URL的链接代码实例
2019/08/30 Python
python 图像处理画一个正弦函数代码实例
2019/09/10 Python
Python打开文件、文件读写操作、with方式、文件常用函数实例分析
2020/01/07 Python
美国蔬菜和植物种子公司:Burpee
2017/02/01 全球购物
医学专业毕业生个人求职信
2013/12/25 职场文书
复核员上岗演讲稿
2014/01/05 职场文书
员工考核管理制度
2014/02/02 职场文书
群众路线专项整治工作情况报告
2014/10/28 职场文书
医院党的群众路线教育实践活动学习心得体会
2014/10/30 职场文书
企业2014年度工作总结
2014/12/10 职场文书
Win10防火墙白名单怎么设置?Win10添加防火墙白名单方法
2022/04/06 数码科技
CSS子盒子水平和垂直居中的五种方法
2022/07/23 HTML / CSS