🌐 一文搞懂跨域问题:原因 + 解决方案 + 面试回答模板
一、什么是跨域?
浏览器出于 同源策略(Same-Origin Policy) 限制,要求:
协议、域名、端口号 三者完全相同才算同源。
若前端请求的接口来源与当前页面不同源,就会触发 跨域问题(CORS)。
示例:
// 当前页面:http://localhost:8080
fetch("http://api.example.com/user") // <-- 域名不同,触发跨域
二、跨域的常见原因
1.协议不同
例如:http:// 和 https://
域名不同
例如:www.example.com 和 api.example.com
端口不同
如 localhost:8080 与 localhost:3000
请求类型复杂
- GET请求通常不会触发预检
- 复杂请求(如 POST、PUT、DELETE、自定义 Header)会先发送 OPTIONS 预检请求,
若后端未正确响应该预检,也会造成跨域错误。
三、跨域的常见解决方案
1.CORS(跨域资源共享)【最常用】
原理:后端通过设置响应头,允许特定源访问资源。
//Node.js/Express示例
app.use((req,res,next)=>{
res.header("Access-Control-Allow-Origin","*") // 或指定域
res.header("Access-Control-Allow-Methods","GET,POST,PUT,DELETE,OPTIONS")
res.header("Access-Control-Allow-Headers","Content-Type,Authorization")
next()
})
优点: 简单、官方推荐
缺点: 需要后端配合;默认不支持携带 Cookie(除非设置 credentials)
⚠️ 注意:如果要在跨域请求中携带 Cookie,需要前后端都设置
Access-Control-Allow-Credentials: true 并且前端的 fetch 要加上 credentials: 'include'。
2.JSONP(旧方案,仅支持GET)
原理: <script> 标签不受同源策略限制。前端通过 callback 参数接收数据。
<script src="http://api.example.com/user?callback=handleData"></script>
<script>
function handleData(data){ console.log(data) }
</script>
优点: 兼容旧浏览器
缺点: 仅支持 GET,不安全、不推荐新项目使用
前端代理转发(开发环境常用)
原理: 在本地开发服务器(如 Webpack、Vite)配置代理,将请求转发至目标后端,实现同源访问。
module.exports={
devServer:{
proxy:'http://api.example.com'
}
}
优点: 无需改后端,开发方便
缺点: 仅适用于开发或部署层面
Nginx 反向代理(生产环境推荐)
原理: 由 Nginx 服务器中转请求,实现跨域资源访问。
location /api/ {
proxy_pass http://api.example.com;
}
优点: 稳定可靠、性能好
缺点: 需要服务器配置权限
四、拓展(面试延伸)
-
为什么只在浏览器有跨域?
因为同源策略是浏览器安全机制,Postman 和 Node 不受限制。 -
OPTIONS 请求是什么?
预检请求,用于确认服务器是否允许跨域访问。 -
CORS 可以允许多个域吗?
可以,后端可根据请求头动态设置Access-Control-Allow-Origin。
总结:
跨域是浏览器的保护机制,不是 bug;想解决它,要么让服务端“同意”,要么让请求“看起来同源”。
五、面试速记模板
跨域问题是由于浏览器的同源策略导致的,只要协议、域名或端口有一个不同,就会被限制访问。
常见解决方案有几种:最常用的是后端开启 CORS,通过设置Access-Control-Allow-Origin等响应头;
其次开发阶段我们可以用 代理转发(如 webpack devServer 或 nginx)规避;
历史方案还有 JSONP 只支持 GET。
实际项目中我通常使用 CORS + 代理 的组合方案来处理跨域。