03-跨域通信和跨tab通信

上一篇文章介绍了什么是“跨域”和“跨站”。可知,“同站”通信也是“跨域”的一种途径。

这次列举一下跨域通信的方法,同时对跨tab通信有启发性价值。

因为前人总结得实在是太齐全了!这里只是做到基本列举齐全,然后做一些小小的补充。

解决跨域问题

同源限制:协议,主机名,端口都相同

更准确地来讲,同源限制体现在2个方面:

1 若向工作在不同源的服务请求,限制响应的处理(client to server) 对于Ajax的影响在于,通过XMLHttpRequest实现的Ajax请求,能向不同的域提交请求,但是不允许获得响应的内容。例如,在abc.example.com下的页面,向def.example.com提交Ajax请求,响应的内容被限制 等等。

2 无法获取不同源的document/浏览器存储数据等BOM和DOM (client to client) 可以说任何有关另外一个源的信息都无法得到:在baidu.com下的页面中包含的js代码,不能访问在google.com域名下的页面内容;甚至不同的子域名之间的页面也不能通过js代码互相访问。

3 例外:但是有三个标签是允许跨域加载资源:<img src=xxx><link href=xxx><script src=xxx>

  • 不能忽略的事实1: 跨域只存在于浏览器端,不存在于安卓/ios/Node.js/python/java等其它环境
  • 不能忽略的事实2: 跨域请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了(这也就是为什么CORS能用的原因)
    • 其实post也可被视为“不受同源规则限制”:在请求时可跨域请求,而且如果可以提交之后不需要返回,这样只是不知道有没有请求成功而已。
      • 如果想要知道是否成功的话,可以一个服务器通知那个提供页面的服务器(即同源的)去返回结果。
    • post的跨域限制的解决,主要是用 nginx后端转发 或者 form提交(页面会刷新跳转到相应页面) 或者 用CORS

跨域各种方法列举–9种

其实就是8种,1种被废弃 注意:单纯的iframe不能跨域,即其是有同源限制的,要结合其他方法才能实现跨域效果。

  • jsonp 只能服务于get啊
  • CORS策略(跨域资源共享策略):主要是后端的处理 (实质上主要用于ajax)
  • 利用HTML5 postMessage:postMessage(send) 和 onmessage。
  • 【在新版本chrome和edge中行不通了】document.domain (这个页面和“另一个页面或者iframe”显式设置成同一个二级域名,服务于特定场景)
  • iframe + window.name
    • 操作:iframe先引用跨域iframe再切换为引用同源的。最终iframe内外是同源,即可从iframe外读取iframe里面的window.name
    • 原理:window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)
      • iframe就是持有window.name的“中间人”了
      • 切换iframe的网址:这个工作通常位于“监听iframe的onload事件”的回调中
    • 缺点:每次通信都要创建一次iframe
    • 参考例子
  • iframe + location.hash
    • 操作:多层嵌套iframe+最内层iframe是同源的+监听hash事件以驱动流程。
    • 原理:因为后来同源了,所以可以使用window.parent.parent
    • 缺点:需要占用iframe的宿主的hash;每次通信都要创建2次iframe
  • Websocket:原生 WebSocket API 使用起来不太方便,我们使用Socket.io轮子
    • ws协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信
    • ws是网络通信协议,所以其实现一定要经过服务器,不能直接client to client
  • nginx反向代理 【常用,而且生产可用,就是需要沟通扯皮】
    • 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。
    • 因为nginx反向代理就使得前后端是同一个域了,就不存在跨域问题了。
  • node中间层代理:和nginx反向代理同理
    • 需要大规模用node才考虑,不然不用考虑;这部分的人员职责难被有效管理

跨域方案的总结:

document.domain被浏览器们废弃,局限性大,而且容易被刷新页面刷掉。

nginx反向代理解决大多数问题,就是可能需要沟通扯皮。jsonp仅限get,不利于统一get post等接口字段规范,用的越来越少。

  • 现代的浏览器,跨域优先考虑CORS,IE 11就全面支持了。
  • (后补充:2022年中,IE浏览器已被废弃)
  • IE8-10,结合iframe和postMessage,POST跨域不在话下。
  • IE6-7,还是iframe,利用iframe父子引用+location.hash。

浏览器tab间通信

建议直接阅读这篇文章

链接中文章的各种方法按“能否跨域”来进行划分,是比较合理的。作为基础,本文已总结出“跨域通信”的方式,这样再看链接文就没有那么困难了。

文章目录
  1. 解决跨域问题
    1. 同源限制:协议,主机名,端口都相同
    2. 跨域各种方法列举–9种
    3. 跨域方案的总结:
  2. 浏览器tab间通信