如何解决前端的跨域问题?一文告诉你

一、什么是"跨域"?

在前端开发中,我们经常听到一个词:"跨域"。那到底什么是跨域呢?我们先从一个生活中的例子说起。

假设你住在一栋公寓楼里,每天都要去隔壁栋的超市买东西。但有一天,物业突然说:"本楼住户只能使用本楼内的设施。"于是你就不能再去隔壁栋的超市了------这就是一种"限制访问"的行为。

在网页世界中,"跨域"其实就是浏览器为了安全考虑,限制网页访问不同域名(或端口、协议)下的资源的一种机制。


1.1 什么情况下会触发跨域?

要判断是否是跨域,只需要记住一句话:

只要请求的URL与当前页面的协议、域名、端口有一个不一致,就会触发跨域。

举个例子:

当前页面地址 请求的目标地址 是否跨域 原因
a.com/index.html a.com/data.json 协议、域名、端口都相同
a.com/index.html a.com/data.json 协议不同(http vs https)
a.com:80/index.html a.com:8080/data.json 端口不同(80 vs 8080)
a.com/index.html b.com/data.json 域名不同(a.com vs b.com

二、为什么会有跨域问题?

跨域问题的核心目的是为了保护用户的安全。

比如你在银行网站登录了账户,然后又打开一个恶意网站,如果这个网站可以直接访问银行网站的数据,那么你的账号信息就可能被盗用。因此,浏览器设置了跨域限制,防止这种"跨站攻击"。


三、常见的跨域场景有哪些?

跨域最常见于前后端分离开发中。比如:

  • 前端运行在 http://localhost:3000
  • 后端接口部署在 http://api.example.com

这时候前端调用后端接口时,就会遇到跨域问题。

再比如,你想通过 JavaScript 获取某个第三方 API 的数据,也可能因为跨域被拦截。


四、如何解决跨域问题?

下面介绍几种常见的解决方案,我们会从易到难逐一讲解,并尽量用通俗的语言说明原理。


4.1 使用 CORS(推荐)

CORS(Cross-Origin Resource Sharing),中文叫"跨域资源共享",是最标准、最推荐的方式。

4.1.1 原理简述:

CORS 的核心思想是:服务器告诉浏览器,"我允许某些特定来源访问我的资源"

这就像物业说:"虽然原则上不允许外来人员进入小区,但我认识隔壁栋的小王,他可以进来。"

4.1.2 如何配置?

服务器端需要设置几个 HTTP 头信息,最常见的有:

http 复制代码
Access-Control-Allow-Origin: *

或者指定允许的域名:

http 复制代码
Access-Control-Allow-Origin: http://your-frontend-domain.com

这样浏览器就知道:"哦,这个接口允许我访问,没问题。"

4.1.3 案例说明:

假设你写了一个前端项目,在本地运行在 http://localhost:3000,你要访问的后端接口是 http://api.example.com/login

如果你发现浏览器控制台报错:

csharp 复制代码
Blocked by CORS policy: No 'Access-Control-Allow-Origin' header present on the requested resource.

这就说明后端没有正确设置响应头,你需要让后端加上:

http 复制代码
Access-Control-Allow-Origin: http://localhost:3000

或者更宽松一点:

http 复制代码
Access-Control-Allow-Origin: *

⚠️ 注意:* 表示允许所有来源访问,但在生产环境中建议指定具体的域名以增强安全性。


4.2 JSONP(过时但曾经流行)

JSONP 是一种比较老的技术,现在基本已经被 CORS 替代,但在一些老旧系统中还能看到它的身影。

4.2.1 原理简述:

我们知道 <script> 标签是可以跨域加载 JS 文件的,所以 JSONP 利用了这一点。

它的工作方式大概是这样的:

  1. 前端定义一个函数,比如叫 handleData(data)

  2. 动态创建一个 <script> 标签,src 指向目标 URL,并带上参数 callback=handleData

  3. 后端返回的内容是一个函数调用,例如:

    js 复制代码
    handleData({ "name": "张三", "age": 25 });
  4. 浏览器执行这个函数,拿到数据。

4.2.2 优点 & 缺点:

  • ✅ 优点:兼容性好,适用于不支持 CORS 的旧浏览器。
  • ❌ 缺点:只能用于 GET 请求;存在安全隐患;代码复杂度高。

4.3 代理服务器(适合开发阶段)

如果你是前端开发者,暂时无法修改后端配置,可以在开发阶段使用"代理服务器"来绕过跨域限制。

4.3.1 原理简述:

代理服务器就像是一个"中间人"。前端把请求发给代理服务器,由它去访问真正的后端接口,然后再把结果返回给前端。

因为代理服务器和后端之间的通信是服务器之间的通信,不受浏览器同源策略限制。

4.3.2 实现方式(以 Vue/React 开发为例):

以 Vue 项目为例,在 vue.config.js 中添加如下配置:

js 复制代码
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://api.example.com',
        changeOrigin: true,
        pathRewrite: { '^/api': '' }
      }
    }
  }
}

这样,前端请求 /api/login,会被代理到 http://api.example.com/login,从而避免跨域。


4.4 Nginx 反向代理(生产环境常用)

如果你已经上线了项目,想彻底解决跨域问题,可以通过 Nginx 配置反向代理。

4.4.1 原理简述:

Nginx 是一个高性能的 Web 服务器,它可以作为前端服务和后端服务之间的桥梁。前端访问的是同一个域名下的路径,而 Nginx 负责将这些请求转发到对应的后端服务上。

4.4.2 示例配置:

nginx 复制代码
server {
    listen 80;
    server_name yourdomain.com;

    location /api/ {
        proxy_pass http://backend-server/;
    }

    location / {
        root /path/to/your/frontend/dist;
        index index.html;
    }
}

这样,前端访问 /api/login,其实是由 Nginx 转发到了后端服务器,前后端都在同一个域名下,自然就不会跨域了。


五、其他注意事项

5.1 简单请求 vs 预检请求(Preflight)

并不是所有的请求都会直接发送过去,有些请求会被浏览器先做一次"预检查",也就是所谓的 Preflight Request(预检请求)

什么情况下会触发 Preflight?

  • 请求方法不是 GET、HEAD、POST;
  • POST 请求的 Content-Type 不是 application/x-www-form-urlencoded、multipart/form-data 或 text/plain;
  • 请求头中带有自定义头部(如 Authorization);
  • 请求中带有 cookie 且 Access-Control-Allow-Credentials 为 true。

这时浏览器会先发送一个 OPTIONS 请求,询问服务器是否允许跨域操作,只有得到肯定答复才会继续发送真实请求。


如果你的请求需要携带 Cookie 或者 Token,也需要特别注意跨域设置。

前端设置:

js 复制代码
fetch('http://api.example.com/user', {
  credentials: 'include'
})

后端设置:

http 复制代码
Access-Control-Allow-Origin: http://your-frontend-domain.com
Access-Control-Allow-Credentials: true

六、总结一下

方法 是否推荐 适用场景 说明
CORS ✅ 推荐 所有场景 最标准的方法,需后端配合
JSONP ❌ 过时 旧项目兼容 只能 GET 请求,不安全
代理服务器 ✅ 推荐 开发阶段 前端本地配置即可
Nginx 反向代理 ✅ 推荐 生产环境 安全、稳定、彻底解决问题

七、结语

跨域问题看起来有点"玄学",但只要你理解了它是浏览器出于安全考虑才做的限制,就能明白为什么会出现这个问题,以及为什么要用特定的方式来解决。

对于刚入门的前端同学来说,掌握 CORS 和代理服务器这两个方案就已经可以应对大部分开发需求了。等你对整个前后端交互流程更熟悉之后,再慢慢学习 Nginx、安全机制等内容也不迟。

希望这篇博客能帮你彻底搞懂"跨域",不再害怕它!

相关推荐
爱编程的喵1 分钟前
React Hooks + 自定义Hooks 打造现代化 Todo 应用:记事本
前端·react.js
咔咔一顿操作4 分钟前
5、Vue中使用Cesium实现交互式折线绘制详解
前端·javascript·vue.js·3d
JosieBook16 分钟前
【web应用】若依框架中,使用Echarts导出报表为PDF文件
前端·pdf·echarts
袁煦丞1 小时前
Photopea云端修图不求人!cpolar内网穿透实验室第641个成功挑战
前端·程序员·远程工作
yk-ddm1 小时前
JavaScript实现文件下载完整方案
前端·javascript·html
万少1 小时前
04-自然壁纸实战教程-搭建基本工程
前端·harmonyos·客户端
karl_hg1 小时前
Element Plus 自定义(动态)表单组件
前端·vue.js·element
南岸月明1 小时前
从焦虑到专注:副业半年后我才明白的3件事
前端
晓13131 小时前
JavaScript加强篇——第八章 高效渲染与正则表达式
开发语言·前端·javascript
南囝coding2 小时前
做付费社群,强烈建议大家做这件事!
前端·后端