浏览器 proxy

0 阅读4分钟

面试题:为什么使用 Proxy(代理服务器)可以解决跨域?

一、先理解:什么是跨域?

浏览器有一个机制:

👉 同源策略(Same-Origin Policy)

所谓“同源”:

必须同时满足:

项目必须相同
协议http / https
域名example.com
端口3000 / 8080

例如:

前端:
http://localhost:3000

后端:
http://localhost:8080

端口不同:

❌ 跨域


二、为什么浏览器要限制跨域?

因为:

👉 防止恶意网站偷数据

比如:

你登录了银行网站:

https://bank.com

然后又打开了:

https://hack.com

如果浏览器不限制:

hack.com 就能:

fetch("https://bank.com/user/money")

直接读取你的银行数据。

所以浏览器必须限制:

❌ 一个源不能随便读取另一个源的数据


三、重点:跨域是谁限制的?

很多人会答错。

❗跨域不是服务器限制的

而是:

👉 浏览器限制的

Node.js 不限制:

// Node.js 可以直接请求任何网站
axios.get("https://api.github.com")

curl 不限制:

curl https://api.github.com

Postman 不限制。

因为:

👉 同源策略只存在于浏览器


四、为什么 Proxy 可以解决跨域?

核心原因:

👉 浏览器认为你请求的是“同源服务器”

例如:


不使用 Proxy

前端:

http://localhost:3000

请求:

http://localhost:8080/api/user

浏览器发现:

项目
当前页面localhost:3000
请求目标localhost:8080

端口不同。

于是:

❌ 跨域


五、使用 Proxy 后发生了什么?

现在:

前端还是:

http://localhost:3000

但请求:

/api/user

注意:

👉 浏览器认为:

请求的是:

http://localhost:3000/api/user

因为没有写 8080。

所以:

✅ 同源请求

浏览器允许。


然后:

👉 代理服务器偷偷帮你转发

代理服务器收到:

/api/user

再转发到:

http://localhost:8080/api/user

整个过程:

浏览器
   ↓
localhost:3000(代理服务器)localhost:8080(真正后端)

六、关键本质(面试高频)

Proxy 不是“消灭跨域”

而是:

👉 “让浏览器以为没有跨域”

因为:

浏览器始终只和:

localhost:3000

通信。

真正跨域通信的是:

👉 服务器和服务器之间

而服务器之间不存在同源策略。


七、经典图解(非常重要)

不使用代理

浏览器
   ↓
localhost:8080

❌ 浏览器发现跨域

使用代理

浏览器
   ↓
localhost:3000  (同源)
   ↓
代理转发
   ↓
localhost:8080

浏览器根本不知道后面还有 8080。


八、Vite / Webpack / Next.js 中的 Proxy

Vite

// vite.config.ts
export default defineConfig({
  server: {
    proxy: {
      "/api": {
        target: "http://localhost:8080",
        changeOrigin: true,
      },
    },
  },
});

前端:

fetch("/api/user")

实际上:

Vite Dev Server
→ 转发到
http://localhost:8080/api/user

九、Next.js Proxy(实际项目常见)

rewrites

// next.config.js
async rewrites() {
  return [
    {
      source: "/api/:path*",
      destination: "http://localhost:8080/api/:path*",
    },
  ];
}

浏览器:

请求:
/api/user

Next.js:

转发:
http://localhost:8080/api/user

十、changeOrigin 是什么?

很多面试官喜欢问。

changeOrigin: true

作用:

👉 修改请求头中的 Host

例如:

原本:

Host: localhost:3000

改成:

Host: localhost:8080

因为有些后端服务器会校验 Host。


十一、Proxy 和 CORS 的区别

这是超级高频题。

方案本质
Proxy绕过浏览器跨域限制
CORS服务器告诉浏览器“允许跨域”

CORS

后端返回:

Access-Control-Allow-Origin: *

浏览器看到:

服务器允许跨域

于是放行。


Proxy

浏览器根本不知道跨域。


十二、面试标准答案(推荐背诵)

浏览器存在同源策略,会限制前端跨域请求。

使用 Proxy 后,浏览器请求的是同源代理服务器,因此不会触发跨域限制。

然后代理服务器再将请求转发到真正的后端服务器。

本质上是把“浏览器跨域”变成了“服务器之间通信”,而服务器之间不存在同源策略,因此可以解决跨域问题。


十三、易错点(高频)

❌ 错误说法

Proxy 让浏览器支持跨域了

错。

浏览器还是不支持跨域。

只是:

👉 浏览器没发现跨域


❌ 错误说法

后端之间也有跨域

错。

跨域是浏览器安全机制。

服务器之间没有同源策略。


十四、项目中的真实架构

实际生产:

用户浏览器
    ↓
Nginx
    ↓
Node.js / Java / Go

Nginx 经常充当:

👉 反向代理(Reverse Proxy)

例如:

location /api {
    proxy_pass http://backend:8080;
}

浏览器:

访问:
https://example.com/api/user

Nginx:

转发:
http://backend:8080/api/user

所以前端永远同源。


十五、延伸面试题

面试官可能继续问:

  • 什么是正向代理和反向代理?
  • CORS 预检请求是什么?
  • 为什么 OPTIONS 会先发送?
  • nginx 为什么能解决跨域?
  • WebSocket 有跨域问题吗?
  • Cookie 跨域为什么复杂?
  • SameSite 是什么?
  • JSONP 为什么能跨域?
  • devServer proxy 原理是什么?
  • rewrite 和 proxy 有什么区别?