写在最前

啊😭!在我大一学习前端,刚入门的时候,尝试着用jquery做一些小项目,这个东西困扰了我一个寒假!!!!当时没有跨域这个概念,于是乎就开始疯狂的百度。。。。为了不拖进度,把一个前后端分离的项目被逼成了不分离,后来还好,在开学前夕顺利解决,把不分离的“不”字去掉了,并也按时完成了项目!!!

(拖了一个月左右应该也叫按时完成吧,不管了,先奖励自己一个🍗~)

跨域问题真的成了我一段时间的心里阴影,后来一谈到跨域,心里贼怕!

最近复习网络部分,刷到了跨域的知识点,于是结合自己毕生所学(加上搜集的一丢资料),总结了一些关于跨域的知识。

什么是跨域?

先举个栗子🌰,我博客的网址是:https://blog.wangez.site:8080
最前面的https叫做协议,随后的blog.wangez.site叫做域名,最后的8080叫做端口号
(注:真实的博客网址不带8080,我的博客,都说了是举个栗子🌰,不会有人当真了吧!!!)。

当前页面中的某个接口请求的地址和当前页面的地址如果协议、域名、端口其中有一项不同,就说该接口跨域了

为什么有跨域?

浏览器为了保证网页的安全,出的同源协议策略

这部分以下摘录自MDN,想详细了解这部分可以去[MDN](浏览器的同源策略 - Web 安全 | MDN (mozilla.org))上看看。

同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。

如果两个 URL 的 protocol、port (en-US) (如果有指定的话)和 host 都相同的话,则这两个 URL 是同源。这个方案也被称为“协议/主机/端口元组”,或者直接是 “元组”。(“元组” 是指一组项目构成的整体,双重/三重/四重/五重/等的通用形式)。

下表给出了与 URL http://store.company.com/dir/page.html 的源进行对比的示例:

URL 结果 原因
http://store.company.com/dir2/other.html 同源 只有路径不同
http://store.company.com/dir/inner/another.html 同源 只有路径不同
https://store.company.com/secure.html 失败 协议不同
http://store.company.com:81/dir/etc.html 失败 端口不同 ( http:// 默认端口是80)
http://news.company.com/dir/other.html 失败 主机不同

跨域报错

image-20210605180026687

当我们测接口的时候,看见数据并没有如约而至,打开我们万能的浏览器控制台,看见了这个报错,不要犹豫,就是遇见了跨域问题!

跨域解决办法

cors

这是我目前写项目最常用的一种解决办法,也是当下最流行的方案,通过设置后端,来解决跨域,简单快捷

传说中的后端跨域!

1
2
3
4
5
6
7
res.setHeader('Access-Control-Allow-Origin', '*'); // 允许跨域的源地址是什么,可以设置为*,也可以设成你的源地址

res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); // 设置返回数据类型

res.setHeader("Access-Control-Allow-Methods", "GET, PUT, OPTIONS, POST"); // 控制哪种请求是可以跨域的

res.setHeader("Access-Control-Allow-Credentials", true); // 跨域的时候是否携带cookie

jsonp

利用的原理是script标签可以跨域请求资源,将回调函数作为参数拼接在url中

传说中的前端跨域!但是需要后端的小伙伴们来配合我们一下哦🙄

​ 后端收到请求,调用该回调函数,并将数据作为参数返回去,注意设置响应头返回文档类型,应该设置成javascript

res.setHeader(‘content-type’, ‘application/javascript’) // 要注意不要忘了设置这个 ,否则会出错误!

1
2
3
4
5
6
7
<script>
function JsonpCallback(data) {
// 在这里处理后端返回来的data数据
console.log(data);
}
</script>
<script src="http://127.0.0.1:12345/jsonp/callback=JsonpCallback"></script>

postmessage

这个是我没听说过的一种方法,它是利用html5的api进行的,具有特定的使用场景。

使用场景:一个页面中嵌入另一个iframe页面,

​ 在主页面中使用postmessage发送数据,在iframe页面中用监听器接收数据

   
1
2
3
4
5
6
7
8
9
10
// 主页面
iFrame.onload = function () {
iFrame.contentWindow.postMessage({ msg: 'MessageFromIndexPage' }, '\*');
}
// iframe页面
window.addEventListener("message", function (event) {

console.log('这里是接收到来自父页面的消息,消息内容在event.data属性中', event)

}, false)

其他方法:node中间件、nginx反向代理、websocket等

主要是因为同源策略是浏览器的限制,服务器和服务器之间没有限制

这次我们举个菠萝🍍,小红想要小绿的新玩具(发出接口请求),但是小绿不给他(同源策略),于是小红去找了小兰,对小兰说,我想要小绿的新玩具(准备去搞中间件进行转发或者做代理了),小兰去跟小绿要来了新玩具(拿到了想要的数据,说明方法成功),并将新玩具交给了小红(解决了跨域)

在这里面我只接触过node中间件跟nginx反向代理,也不算很深入的了解,所以就先不献丑啦,等日后学有所成再来填上这个坑!

最后

跨域是很常见的一个问题,也是出现在面试问题中频率比较高的问题,希望每个小伙伴们在遇到这个问题的时候都能顺利解决。虽然我们现在写项目的时候,框架中大都为我们配置了代理(Vue的proxyTable代理等),但是我想了解其根源对于我们的自我提高是非常有帮助的!