• WebSocket


    背景

    经常见到,但一直没在工作中用到过。一次讨论中,大概了解了一些,就是那个神奇的postMessage方法

    websocket场景:

    允许服务端主动向客户端推送数据。

    具体问题:

    问题1:
    一个页面A(系统A),内嵌平台的系统B。希望能在A中感知到B的任务创建动作,有什么办法呢?A如何监听到B发出的网络请求,或者监听B某一个控件的click事件。
    限制:不能改平台B系统的代码。页面A要独立完成这个功能。实在不行,再让系统B做小小的改动,支持下页面A。系统A和系统B的域名不同,非同源
    问题2:
    A内嵌B除了iframe嵌入,还有别的什么方法呢?

    业务使用场景:

    主系统A上要通过组件的方式加载一个小系统B。
    点击系统A上的按钮,就可以打开系统B的窗口式界面。用户在B中填写完信息,并提交。数据就进入系统A了。但是如何让系统A知道你填完信息了呢?
    这就需要系统B给系统A通信。
    postMessage方法就派上用场了。系统B上的保存按钮,调到了系统A上的接口,系统A后台处理完数据,服务端就要给客户端发送请求了。
    大概是这么个场景,就是不知道最后的解决方法是什么?容后再记!

    假如用postmessage实现:(待完善,不一定正确)
    系统B创建完任务后,主动推送消息给系统A页面
    系统B的任务创建功能中要加如下代码:

    worker = new Worker( url )  // url是系统A的url吧
    worker.postMessage( data) 
    
    • 1
    • 2

    系统A页面要加如下代码:

    worker.onmessage
    
    • 1

    WebSocket是一种在单个TCP连接上进行全双工通信的协议。
    WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

    worker主线程:
    1)通过 worker = new Worker( url ) 加载一个JS文件来创建一个worker,同时返回一个worker实例。
    2)通过worker.postMessage( data) 方法来向worker发送数据。
    3)绑定worker.onmessage方法来接收worker发送过来的数据。
    4)可以使用 worker.terminate() 来终止一个worker的执行。
    WebSocket是Web应用程序的传输协议,它提供了双向的,按序到达的数据流。他是一个Html5协议,
    WebSocket的连接是持久的,他通过在客户端和服务器之间保持双工连接,服务器的更新可以被及时推送给客户端,而不需要客户端以一定时间间隔去轮询。

    跨域

    浏览器的同源策略
    同源是指相同的域名、协议和端口,只要其中一项不同就为跨域。

    • JSONP因为仅支持get请求,淘汰无人问津是迟早的事情
    • CORS支持所有类型的HTTP请求,是跨域HTTP请求的根本解决方案,但是我们上一篇也提了,还是有IE兼容问题
    • postMessage方法允许来自不同源的脚本进行有限的通信,只要能获取到源和窗口对象就可以实现跨域消息传递
    • websocket本身不受同源策略的限制,可以在不同源间进行通信

    iframe的postMessage方法

    iframe页面并不能直接操作父窗口的元素。可以使用html5的postMessage()解决。
    一个窗口可以获得对另一个窗口的引用,然后在窗口上调

    window.postMessage()
    targetWindow.postMessage()
    targetWindow.postMessage(message, targetOrigin, [transfer]);
    
    • 1
    • 2
    • 3
    • targetWindow: 其他窗口的一个引用。例如:window.parent父窗口
    • message: 将要发送到其他 window 的数据。
    • targetOrigin: 通过窗口的 origin 属性来指定哪些窗口能接收到消息事件。*或者url
    • transfer 可选: 是一串和 message 同时传递的 Transferable 对象。这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

    举例:
    只有父窗口是http://a.123.com:8080时才会接受到传递的消息。

    window.parent.postMessage('hello world','http://a.123.com:8080/index.html')
    
    • 1

    ifame父子窗口通信(子通信父)

    子对父说,关闭iframe targetWindow.postMessage(data, '*')
    父监听到子发的消息,然后做了相应的处理

    window.addEventListener('message', function(e) {
    var e = e || window.event;
    switch (e.data.command) {
    case 'close': document.getElementByTagName('body')[0].removeChild(document.getElementByTagName('ifram')[0]);
    }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    a.html窗口对window.open新打开的b.html窗口进行通信
    在这里插入图片描述
    在这里插入图片描述

    跨域会引起的安全问题

    安全问题
    1、如果你不希望从其他网站接收message,请不要为message事件添加任何事件监听。
    2、如果你确实希望从其他网站接收message,请始终使用origin和source属性验证发件人的身份。任何窗口都可以向任何其他窗口发送消息,并且你不能保证未知发件人不会发送恶意消息。而且在验证身份后,你仍然应该验证接收到的消息的语法,防止非法攻击(例如SQL注入)。
    3、使用postMessage将数据发送到其他窗口时,应该指定精确的目标origin,而不是*。恶意网站可以在你不知情的情况下更改窗口的位置,因此它可以拦截使用postMessage发送的数据。

    如何解决跨域问题

    JSONP:
    原理是:动态插入script标签,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url
    参数中指定的函数,并且会把我们需要的json数据作为参数传入。
    由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源,为了实现跨域
    请求,可以通过script标签实现跨域请求,然后在服务端输出JSON数据并执行回调函数,从而解决了跨
    域的数据请求。
    优点是兼容性好,简单易用,支持浏览器与服务器双向通信。缺点是只支持GET请求。
    JSONP:json+padding(内填充),顾名思义,就是把JSON填充到一个盒子里

    代码
    functioncreateJs(sUrl){
    var oScript =document.createElement(‘script’);
    oScript.type = ‘text/javascript’;
    oScript.src= sUrl;
    document.getElementsByTagName(‘head’)[0].appendChild(oScript);
    } c
    reateJs(‘jsonp.js’);
    box({
    ‘name’: ‘test’
    });
    functionbox(json){
    alert(json.name);
    }

    CORS:
    服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测
    到相应的设置,就可以允许Ajax进行跨域的访问。
    通过修改document.domain来跨子域
    将子域和主域的document.domain设为同一个主域.前提条件:这两个域名必须属于同一个基础域名!而
    且所用的协议,端口都要一致,否则无法利用document.domain进行跨域
    主域相同的使用document.domain
    使用window.name来进行跨域
    window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有
    的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是
    持久存在一个窗口载入过的所有页面中的
    使用HTML5中新引进的window.postMessage方法来跨域传送数据
    还有flash、在服务器上设置代理页面等跨域方式。个人认为window.name的方法既不复杂,也能兼容
    到几乎所有浏览器,这真是极好的一种跨域方法。

    参考:
    《postMessage和webSocket》http://www.bijilu.com/1553.html
    《在IFrame中使用postMessage跨域》https://www.jianshu.com/p/9e98b4e6ca0e

  • 相关阅读:
    精通Nmap:网络扫描与安全的终极武器
    啊,CET6----六级高频词
    深度学习之wandb的基本使用
    23~49(构造函数+继承+类的本质+ES5中的新增方法)
    SpringBoot框架集成Dubbo
    【无标题】
    Linux: code: name: void dev_deactivate(struct net_device *dev)
    Linux:read 从键盘读入变量值
    数论分块 学习笔记
    开关电源环路稳定性分析(04)-电压控制模式
  • 原文地址:https://blog.csdn.net/AriesTina/article/details/127596178