02-跨域通信和跨tab通信

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

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

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

解决跨域问题

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

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

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

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

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

跨域各种方法列举–9种

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

  • jsonp 只能服务于get啊
  • CORS策略(跨域资源共享策略):主要是后端的处理 (实质上是ajax)
  • 利用HTML5 postMessage (有关联的窗口之间的按约定通信,若搭配iframe跨域能力更强)
  • document.domain (这个页面和“另一个页面或者iframe”显式设置成同一个二级域名,服务于特定场景)
  • 利用iframe父子引用+location.hash
  • 利用iframe父子引用+切换src + windows.name
  • Websocket:原生 WebSocket API 使用起来不太方便,我们使用Socket.io轮子
    • ws协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信
    • ws是网络通信协议,所以其实现一定要经过服务器,不能直接client to client
  • nginx反向代理 【常用,而且生产可用,就是需要沟通扯皮】
    • 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。
    • 因为nginx反向代理就使得前后端是同一个域了,就不存在跨域问题了。
  • node中间层代理:和nginx反向代理同理
    • 需要大规模用node才考虑,不然不用考虑;这部分的人员职责难被有效管理

跨域方案的总结:

document.domain局限性大,而且容易被刷新页面刷掉。nginx反向代理解决大多数问题,就是可能需要沟通扯皮。jsonp颇有FaaS的味道,但是怕被刷接口攻击。

  • 现代的浏览器,跨域优先考虑CORS,IE 11就全面支持了。
  • IE8-10,结合iframe和postMessage,POST跨域不在话下。
  • IE6-7,还是iframe,利用iframe父子引用+location.hash。

浏览器tab间通信

浏览器同源指的是协议,域名,端口都相同

sessionStorage不能跨标签或者窗口

只能“同源”的思路:

  • localStorage + onstorage事件(若设置了相同document.domain可以跨二级域名)
    • onstorage事件是非当前(且需同源的)页面对localStorage进行修改时才会触发;当前页面修改localStorage不会触发本页面的监听函数
  • IndexedDB也是基于浏览器数据存储,区别是其实现通信需要轮询
  • SharedWorker 共享工作线程(只能同源,兼容性差)
  • Service Worker(加postMessage) (没有详细研究过)

能跨域的思路:

  • 使用cookie(Cookie中的同源只关注域名,忽略协议和端口,也就是Cookie可以跨二级域名来访问,也可以称为“同站”)
  • document.domain已介绍了不是特别好用
  • postMessage (能跨域) 尤其是可以在window.open父子tab之间使用
    • postMessage + MessageChannel
    • postMessage + BroadCastChannel
  • websocket用服务器做中转
  • iframe作为某个页面的“僚机”
文章目录
  1. 解决跨域问题
    1. 同源限制:协议,域名,端口都相同
    2. 跨域各种方法列举–9种
    3. 跨域方案的总结:
  2. 浏览器tab间通信