面试题:为什么使用 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 有什么区别?