同源策略
-
什么是同源?
- 使用
window.origin
或者location.origin
可以获得当前源 - 源:协议+域名+端口号
- 如果协议、域名、端口号完全一致,那么就可以说这两个
url
是同源的。
- 使用
-
同源策略
- 浏览器规定如果JS运行在源A中,那么只能获取源A得数据,不能获取源B的数据,即不允许跨域
- 这是浏览器故意设计的功能,目的是为了保护用户隐私。
跨域
但是大多数时间,我们往往都需要进行跨域访问。
-
CORS跨域
跨源资源共享(CORS)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它源,使得浏览器允许这些源访问加载自己的资源。[1]
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。 因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。[2]
我们在手动设置CORS时只需在服务器端添加:
response.setHeader('Access-Control-Allow-Origin','*')
。一般来说我们在设置源字段的时候都会填写一个域名,* 则代表可以接受所有域名的加载资源请求。 -
JSONP跨域
当我们无法使用CORS进行跨域时,可以考虑使用JSONP来进行跨域。
JSONP的原理纯属套娃,其本质就是使用回调函数来进行一个的套。
因为在HTML中,script的src属性本身是一个不会产生跨域的GET请求,我们可以通过定义一个全局回调函数,同时引用服务器端的js文件(文件中含有经过服务器端处理过的包含我们所需数据的同名函数),js在执行后,就是变相执行了我们一早就定义好的全局回调函数(因为他们是同名的),从而解决了我们的需求。这么说来可能有些拗口,可以参考以下过程:
本地:
1 2 3 4
//定义全局回调函数 window.dataSource(data) =>{ console.log(data) }
服务器端:
1 2 3 4 5 6 7 8 9 10 11 12 13
//将我们需要的数据装进一个js内,由其他人调用 if (path === '/data.js'){ response.statusCode = 200 response.setHeader('Content-Type','text/javascript;charset=utf-8') //写所引用js内容,并字符串化 const string = fs.readFileSync('./public/data.js').toString() //写所需数据内容,并字符串化 const data = fs.readFileSync('./public/data.json').toString() //将所需数据替换占位符 const dataSource = string.replace('{{data}}',data) //将数据写入data.js作为res response.write(dataSource) }
1 2 3
//data.js中 //dataSource为同名函数 window.dataSource({{data}})
本地:
1 2 3 4
//动态引入data.js const script = document.createElement('script') script.src = '.../data.js' document.body.appendChild(script)
我们在本地引用
data.js
后,服务器端首先发现我们的请求,并将我们所需的内容写入data.js
作为回应发送给我们。我们引用的是什么?如果弄清了上述流程,应该发现我们引用的是一句非常简单的window.dataSource(data)
。而window.dataSource
正是我们一开始定义在本地的一个函数!我们从移花接木地从服务器端拿来了我们需要的数据并执行,也就可以如愿以偿的console.log
出我们需要的东西。可以说是顶级套娃🪆。