跨域 🌒

概述

因为浏览器的同源策略,会有不同协议 ( https 和 http ),不同域名(qq.com, 163.com)、不同端口(80,81)网站之间的跨域问题

同源策略

缘起

同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制

定义

如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源。反之,则不同源。

以上是来自 MDN 的对于同源策略的官方描述。

示例如下:

URL 结果 原因
http://alpha.beta.com/post/article.html - -
http://alpha.beta.com/news/article.html 😄 -
http://alpha.beta.com/news/help.html 😄 -
https://alpha.beta.com/post/article.html ☹️ 不同协议 ( https 和 http )
http://alpha.beta.com:81/post/article.html ☹️ 不同端口 ( 81 和 80)
https://gamma.beta.com/post/article.html ☹️ 不同域名 ( alpha 和 gamma)

源的继承

下面是几种我认为不错的解决方式,及实现原理。

jsonp

流程

  1. 创建一个函数,保证其函数名的唯一性。如uniqueCallbackName
  2. 创建一个script标签,设置其src属性为 https://abc.xyz/api/jsonp?callbackName=uniqueCallbackName
  3. 服务端监听此api,获取到参数{ callbackName: uniqueCallbackName }
  4. 返回给客户端,
1
2
3
4
5
6
window.uniqueCallbackName({
code: 0,
data: {
text: "hello world!"
}
});

5.客户端函数uniqueCallbackName被调用,打印出hello world!

实现代码

1.代码如下:

1
2
3
4
5
6
7
8
// get a unique name
let now = new Date().getTime();
let random = Math.random().toString().substr(2,8);
let unique = now + random;
// create a new callback function
let `name${unique}` = ({data: text}) => {
console.log(text)
}

2.代码如下:

1
2
3
let script = document.createElement("script");
script.src = `https://abc.xyz/api/jsonp?callbackName=name${unique}`;
document.body.append(script);

3.4.

1
2
3
4
5
6
7
8
9
10
11
// nodejs
(request, response) => {
let name = request.body.data.callbackName;
let result = `window.${name}({
code: 0,
data: {
text: 'hello world!'
}
})`;
response.end(result);
};

5.代码如下:

1
hello world!