什么是跨域?
先看一下 URL
有哪些部分组成,如下:
1 | https://github.com:80/gauseen/blog?issues=1#note |
protocol(协议)、host(域名)、port(端口)有一个地方不同都会产生跨域现象,也被称为客户端同源策略
本地存储受同源策略限制
客户端(浏览器)出于安全性考虑,无论是 localStorage
还是 sessionStorage
都会受到同源策略限制。
那么如何实现跨域存储呢?
window.postMessage()
想要实现跨域存储,先找到一种可跨域通信的机制,没错,就是 postMessage
,它可以安全的实现跨域通信,不受同源策略限制。
语法:
1 | otherWindow.postMessage('message', targetOrigin, [transfer]) |
otherWindow
窗口的一个引用,如:iframe
的contentWindow
属性,当前window
对象,window.open
返回的窗口对象等message
将要发送到otherWindow
的数据targetOrigin
通过窗口的targetOrigin
属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"
(表示无限制)
实现思路
用 postMessage
可跨域特性,来实现跨域存储。因为多个不同域下的页面无法共享本地存储数据,我们需要找个“中转页面”来统一处理其它页面的存储数据。为了方便理解,画了张时序图,如下:
场景模拟
需求:
有两个不同的域名(http://localhost:6001
和 http://localhost:6002
)想共用本地存储中的同一个 token
假设:
http://localhost:6001 对应 client1.html 页面
http://localhost:6002 对应 client2.html 页面
http://localhost:6003 对应 hub.html 中转页面
启动服务:
使用 http-server
启动 3 个本地服务
1 | npm -g install http-server |
简单实现版本
client1.html 页面代码
1 | <body> |
hub.html 中转页面代码
1 | <body> |
client2.html 页面代码
1 | <body> |
浏览器打开如下地址:
具体效果如下:
改进版本
分成 2 个 js 文件,一个是客户端页面使用 client.js
,另一个是中转页面使用 hub.js
1 | // client.js |
1 | // hub.js |
页面使用:
1 | <!-- client1 页面代码 --> |
1 | <!-- hub 页面代码 --> |
1 | <!-- client2 页面代码 --> |
总结
以上就实现了跨域存储,也是 cross-storage 开源库的原理。
通过 window.postMessage()
api 跨域特性,再配合一个 “中转页面”,来完成所谓的“跨域存储”,实际上并没有真正的在浏览器端实现跨域存储,
这是浏览器的限制,我们无法打破,只能用“曲线救国”的方式,变向来共享存储数据。
所有源码在这里:跨域存储源码
欢迎关注无广告文章公众号:学前端