首页/文章/http-网络

跨域及解决方案

2024-08-08
24579 分钟
...

同源策略是浏览器的一个重要安全机制,它用于限制一个来源的文档或脚本如何能够与另一个来源的资源进行交互。同源策略要求只有当两个URL的协议、主机和端口都相同时,才被认为是同源。否则,浏览器会认为它们是跨域的。

在早期,服务器端渲染的应用通常不会有跨域问题,因为前端代码和后端API都是在同一个服务器上运行的。随着前后端分离的出现,前端代码和后端API经常部署在不同的服务器上,这就引发了跨域问题。

先来看一下跨域问题怎么产生的:

首先我们在localhost:8000上提供了一个api接口,然后通过nodemon去运行这个node程序。

新建一个html文件,文件中使用fetch向localhost:8000发送请求,并使用LiveServer打开这个html文件

由于LiveServer运行在5501端口而node程序运行在8000端口,不同源,因此产生了跨域问题。

先上解决方案:

  • 把API和静态资源部署到同一个服务器上
  • CORS(Cross Origin Resource Sharing),跨域资源共享
  • node代理服务器(webpack配置proxy代理就是这个),这个是开启了一个node服务器代理,然后由这个node代理请求到资源以后再把资源返回给客户端,因为同源策略的限制是浏览器的限制,而node服务器发送请求是不会受到同源策略限制的,所以不会出现跨域问题。这个node代理服务器使用到的是一个http-proxy-middleware插件进行代理的
  • Nginx反向代理

接下来我们来细说这些方案:

把API和静态资源部署到同一个服务器上且同一个端口下:

上面代码可以指定浏览器访问8000端口的时候,如果要找静态资源去./static文件夹下查找。这样8000端口既提供了api又提供了静态资源,当然这种情况下静态资源和api就是同源的,不会产生跨域问题

使用cors。

cors是一种基于http header的机制,该机制通过允许服务器标示除了它自己以外的其它源(域、协议和端口),使得浏览器允许这些 origin 访问加载自己的资源。

设置的解释:

Access-Control-Allow-Origin:允许所有域名访问(你也可以指定特定的域名,例如'example.com')。

Access-Control-Allow-Methods:允许的HTTP请求方法。

Access-Control-Allow-Headers:允许的HTTP请求头。

另外我们可以了解一下浏览器机制,关于预请求和实际请求:

预检请求(Preflight Request):

对于复杂请求(如使用非简单方法:PUT, DELETE 或自定义头),浏览器会先发送一个OPTIONS请求,询问服务器是否允许跨域请求。

服务器如果同意跨域请求,则返回包含CORS头信息的响应。

实际请求(Actual Request):

如果预检请求被允许,浏览器会发送实际请求,并且会在请求头中包含一些CORS相关的头信息。

服务器在响应中包含CORS头信息,这些信息会被浏览器验证。并允许客户端进行跨域请求。

另外针对复杂请求,因为预检请求是一个options的请求,所以上述代码中我们对options请求进行了单独的处理

这时候我们在5501端口访问8000端口的api,发现也是成功的

使用node代理服务器

在我们平时开发中,我们并不会,也不能直接去修改服务器(当然自己开发的服务器除外),那么开发过程中我们遇到跨域问题应该如何解决呢?相信我们在开发的时候做过类似的配置的:

不管是Webpack,还是Vite,它们底层都是通过开启一个新的Node服务器代理来解决跨域的。原理是vite或Webpack给我们开启了一个服务器,我们请求接口的时候vite或Webpack开启的服务器上请求,然后由这台服务器把我们的请求转发到真实的接口服务器上,而由于同源策略只在浏览器上限制资源的共享,并不限制服务器的请求,所以这样就不会产生跨域问题。

这一段配置的意思是,我在发送请求的时候,如果以/api/开头的请求,node服务器,请你帮我代理到http://localhost:8000 上去请求数据,但是如果没有重写/api路径的话,代理会请求http://localhost:8000/api/{realPath}。 但是因为在http://localhost:8000 上的接口地址是没有/api前缀的,所以请求会报错,这里之所以我们请求的时候写上/api,只是为这个请求路径做一个标识,告诉服务器,这个路径你需要帮我代理,而真实的路径是去请求http://localhost:8000/{realPath} 而不需要中间的/api,所以我们要把/api/给重写成空的字符串。

示例如下:

并且这时候,我们在localhost:8000上也关闭掉原来的cors:

发现也是可以正常访问的:

使用Nginx

使用Nginx解决跨域访问分为2种情况。

<1>静态资源和api都通过nginx服务器做了一层代理(这种情况下不会有跨域问题)

<2>只有api通过nginx做了一层代理,而静态资源仍然从另一台静态资源服务器中获取(这种情况下有跨域问题)

第一种情况去配置nginx如下:

可以看到我们在浏览器上通过localhost:8080进行访问的时候,可以定位到 C:\Users\**\static\index.html 文件,并且在页面中通过

http://localhost:8080/api/users/list

请求接口的时候,可以被转发到http://localhost:8000/users/list。

上面就是情况一:静态资源和api都通过nginx服务器做了一层代理的情况。也就是用户拿静态资源,请求api都经过nginx服务器,由nginx服务器统一去请求静态资源和api数据,最后返回给用户。

但是,如果我们通过liveServer打开html的时候,就会产生跨域问题,因为此时静态资源是从localhost :5501里面获取的,而页面上去调用接口的地址是http://localhost:8080/api/user/list。 虽然这个地址会被nginx代理到 http://localhost:8000/user/list ,但是仍然会产生跨域问题。

此时加上如下配置,为nginx在8080端口开启的这个服务器开启了cors,指定8080端口可以允许所有源访问。

此时可以看到,跨域问题得到了解决。

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
http-网络2025-08-06
按下回车后网页是怎么出来的
当你在浏览器中输入一个网址,比如 ,然后按下回车键,几秒钟后页面就完整地呈现在你眼前。这个看似简单的操作,背后其实是一整套精密协作的网络机制在起作用。本文将带你从基础讲起,理解 Web 开发中最重要的网络知识,帮助你搞清楚: 数据是如何从服务器传到你的电脑,并最终变成网页的? 一、互联网通信的分层模型:OSI 七层模型 为了管理复杂的网络通信,工程师们提出了一个通用的参考模型—— OSI 七层模型 。它把整个通信过程划分为七个层次,每一...
学习面试
http-网络2025-03-04
网络代理详解
一、 的基础概念 1\. 什么是代理? 代理是一种通过中间服务器来帮助 访问目标服务器的技术。代理服务器位于客户端与服务器之间,充当两者的中介,从而实现客户端和服务器之间的隔离。用户的所有请求经过代理后,再发往目标服务器,而目标服务器的响应则返回代理,再由代理传递给用户。 2\. 网络代理的工作流程 在基本的网络代理工作流程中, 扮演了“请求转发者”和“响应返回者”的角色: 1. 客户端请求 :客户端将请求发送到代理服务器,而不是直接发...
学习面试
http-网络2024-11-29
没有koa的cors你怎么处理跨域?
关联问题: JSONP有何局限性 CORS如何处理复杂请求 代理在生产环境效果如何 前言 “金九银十”的秋招,就像是落进池塘的羽毛,连点水花都没砸起来。已读不回是常态,能给面试已是情分,能拿offer的更是少之又少。可怜我在寒潮来临的深秋之际,也只得哀叹一句“越来越冷了啊...” 不过人总是要吃饭的,所以再怎么冷,卖炭翁也得卖炭,牛马攻城狮也得“攻城”,既是为了填饱肚子,也是为了“春天”做准备。所以今天为各位前端工程狮细聊一下前端面试中...
学习面试
http-网络2024-09-11
面试常客系列之跨域前言
跨域?什么是跨域呢?我们先来看看一个url的组成, ,这一个url我们可以分成四部分来看 是协议, 是域名, 是端口, 是路径.在浏览器中,我们从一个域名发送请求到另一个域名,如果两个域名的协议,域名,端口三部分只要存在一部分不同就会发生跨域,也就是说只有两个域名的协议,域名,端口都相同才会不会发生跨域,所以我们又如何解决跨域的问题呢?在下文中会给大家介绍几种方法去解决跨域问题. 那么要解决跨域就不得不谈及 ,同源策略是一种安全措施,用...
学习面试
http-网络2024-09-02
HTTP缓存:别傻傻不会回答了
前言 在有大量数据交换的应用程序中,我们会采取一些方式将那些实时性要求不高的数据生成副本,并存储在某个相对来说可以快速到达、访问、获取的仓库,这样在需要这些数据的时候可以直接从这个仓库中获取数据。 缓存的目的: 提升数据交换的性能,提高速度。 缓解服务器或数据库的压力。 HTTP 根据是否要向服务器发送请求将缓存规则分为两类:强缓存和协商缓存。 强缓存 在强缓存中,如果命中缓存,则直接从缓存数据库中取出资源,无需再发送请求到服务器上。...
学习面试
http-网络2024-08-19
网络-navigator.sendBeacon前言
navigator.sendBeacon 是浏览器的 API,用于在浏览器后台发送异步请求,它不会等服务端响应。 它可以用于在页面卸载或关闭的时候,发送数据,以及在不阻塞页面卸载的情况下发送数据。 使用 方法发送的请求是异步的,不会阻塞页面的卸载或关闭过程。 这对于需要在用户离开页面之前发送数据的情况非常有用。 优点 不受页面卸载过程的影响,确保数据可靠发送。 普通的 请求如 和 在页面关闭或者刷新、前进、后退等操作时 , 这些请求有可...
学习面试

评论

请登录后发表评论

去登录
加载评论中...

目录