跨域就是请求同源策略限制的请求
同源策略是一种约定,域名、协议、端口号相同即为同源,帮助我们在浏览器进行隔离。
目的:为了保护用户信息的安全,防止恶意窃取数据
1.cookie、localStorage 和 indexDB 无法读取等
2.dom 无法获得
3.ajax 不能发送
1.表单提交
2.img、iframe、script(jsonp)、link
jsonp 的原理就是利用 script 标签没有同源策略限制,通过 script 标签 src 属性,发送带有 callback 参数的 GET 请求,服务端接口返回数据拼凑到 callback 函数中,浏览器收到响应就会执行 callback 函数,接下来看我之前写过的> 例子,会一目了然,简单列举一下
//客户端
var script = document.createElement('script');
script.type = 'text/javascript';
// 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
script.src = 'http://www.duanxl.com:8080/getuser?callback=handleCallback';
document.head.appendChild(script);
// 回调执行函数
function handleCallback(res) {
alert(JSON.stringify(res));
}
//服务端
ctx.res.write(`<script>initResoure("${content}")</script>`);
CORS 是 W3c 的一个标准,允许浏览器向跨源服务器请求数据
我们可以通过配置响应头来达到跨域许可,用于说明接收哪些可允许的域
1.Access-Control-Allow-Origin 必选,它的值要么是请求时 Origin 字段的值,要么是一个*,表示接受任意域名的请求。
2.Access-Control-Allow-Credentials 可选,是一个 Boolean 值,表示是否发送 cookie
3.Access-Control-Expose-Headers 可选,是否可以拿到其他字段
与上面的 CORS 原理一样,通过配置文件设置响应头等字段
我们知道在使用 BFF 架构模式时,node 本身帮我们解决了跨域问题,具体就不说了
比如我们有两个网页一级域名相同,二级域名不同,我们可以通过设置 document.domian 来解决跨域
document.domain共享cookie
test.xxx.com a.html
==================
<script>
document.cookie="aaa";
document.domain="test.com";
</script>
test2.xxx.com b.html
===================
<script>
var data=document.cookie;
</script>
当然,我们也可以配置 iframe 等方式,再通过 location.hash 传值,达到域之间的数据共享
我们知道,当使用了 iframe 时,window.name 将共享当前数据,window.name 一般是指 window 的名称,window.name 可以容纳很大的值(最大 2M),我们完全可以将需要共享的数据放在 window.name 上,这样也是解决跨域的一种方式
postMessage 是 html5 新的 api,接收两个参数 postMessage(data,orign)
第一个参数只能是字符串,我们可以使用 JSON.stringify 序列化数据
//a.html
window.postMessage('test data','http://www.domain.com')
//b.html
window.addEventListener('message', function(e) {
alert('data from domain2 ---> ' + e.data);
}, false);
WebSocket protocol 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是 server push 技术的一种很好的实现。
//客户端
const url='ws://xxx.xxx:2222';
const socket=new WebSocket(url);
socket.onopen=()=>{
//成功建立时触发
}
socket.onmessage=(data)=>{
//收到消息时触发
}
socket.onclose=()=>{
//断开链接时触发
}
socket.onerror=(e)=>{
//异常
}
//服务端我们可以使用socket-io,这里我就不写了,明白用法即可
MessageChannel 又称为点对点通信,就是两个对端口,一个发送,一个接收
var channel = new MessageChannel();
var para = document.querySelector('p');
var ifr = document.querySelector('iframe');
var otherWindow = ifr.contentWindow;
ifr.addEventListener("load", iframeLoaded, false);
function iframeLoaded() {
otherWindow.postMessage('Hello from the main page!', '*', [channel.port2]);
}
channel.port1.onmessage = handleMessage;
function handleMessage(e) {
para.innerHTML = e.data;
}
BroastcastChannel 又称为广播消息
const bc = new BroadcastChannel('channel1')
const bc2 = new BroadcastChannel('channel1')
bc2.onmessage = (eve) => {
console.log('bc:', eve.data);
}
setTimeout(() => {
bc.postMessage({message: 'hello'})
}, 1000);
其实 BroastcastChannel、MessageChannel、PostMessage 这三种方式都可以实现深拷贝,因为我们可以利用通信,将对象直接发送,这也算是一种特例
当然,还有很多解决跨域的方法,比如 jQuery、axios 等提供的 API,先简单介绍到这里,如果有理解不对的地方,欢迎联系我微信:d15540940134