本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
今天周五,我在群里看到不少划水的网友聊到前端弱鸡,curl 和 postman 等都能跨域,为啥你前端不能跨域?为此,还有人给前端理论,说他们前端哑口无言,标准是个菜。还有网友说,他问了他的同事,他前端同事说是 http 协议的问题。
讨论来讨论去,只有少部分网友是清醒的,跨域问题其实是浏览器”自作多情”,那么它为什么要限制跨域呢,而 curl、Postman 等却能畅通无阻?下面我们一起来看看跨域问题的终极解析。
一个让前端开发者抓狂的悖论
相信很多开发者都经历过这样的魔幻时刻,某天你终于在 Postman 里调通了一个 API 接口,它响应迅速,数据完美;可当你把同样的 URL 给到前端,结果它在浏览器里却毫不留情地甩出一个红色错误。
Access to fetch at 'https://api.xttblog.com/data' from origin 'http://localhost:3000'
has been blocked by CORS policy...
这一刻,前端或许会怀疑人生:到底是接口有问题,还是浏览器在故意跟我作对?
下面,我们就来一起揭开跨域问题的神秘面纱吧,彻底搞懂这个“浏览器专属”的难题。
跨域到底是什么?
要聊跨域问题,必须提到同源策略,下面我们先来看看什么是同源策略吧。
什么是同源?
跨域问题的根源在于浏览器的同源策略(Same-Origin Policy)。所谓同源,是指两个 URL 的协议、域名、端口号三者完全一致。
举个例子,以下 URL 与 http://store.xttblog.com/dir/page.html 的对比。
| URL | 是否同源 | 原因 |
|---|---|---|
http://store.xttblog.com/dir2/other.html | 是 | 仅路径不同 |
https://store.xttblog.com/secure.html | 否 | 协议不同(http vs https) |
http://store.xttblog.com:81/dir/etc.html | 否 | 端口不同(默认80 vs 81) |
http://news.xttblog.com/dir/other.html | 否 | 域名不同 |
注意,这里是浏览器的同源策略,不是 curl、postman、http 等的同源策略。
跨域限制的行为
一旦触发跨域,浏览器会严格限制以下操作。
- AJAX/Fetch 请求:不同源的接口请求被默认拦截
- DOM 访问:无法通过 JS 操作跨域 iframe 的内容
- 数据存储:无法读取跨域的 Cookie、LocalStorage 等
和上面我强调的一样,这里的关键认知同样是,同源策略是浏览器独有的安全机制,它就像一位尽职的保安,严格检查每一个进出浏览器的请求,防止恶意网站窃取你的隐私数据。
跨域限制只存在于浏览器中
那么,为什么浏览器要“多事”,而 Postman/curl 却畅通无阻?
这可能是跨域问题中最反直觉的部分。答案其实很简单:跨域限制只存在于浏览器中!
Postman 和 curl 是独立的 HTTP 客户端工具,它们直接与服务器通信,不受同源策略的约束。这就好比:
- 浏览器:住在小区里的居民,出门必须经过保安(同源策略)的检查
- Postman:外来的快递员,直接走物流通道,保安管不着
浏览器限制跨域请求的核心目的是防范CSRF(跨站请求伪造)攻击。想象一下,如果没有同源策略,你登录网银后不小心访问了恶意网站,这个网站就可以通过你的身份凭证偷偷向银行发起转账请求,后果不堪设想。
而 Postman 作为开发工具,发送请求时不会自动附带浏览器的 Cookie 等凭证,天然不存在这种安全风险。curl 也同样,不会主动附带浏览器的 Cookie 等凭证。只有浏览器,由于 http 是无状态协议,因此它需要携带一些 cookie 等凭证。那你访问了那么多网站,该带谁的凭证,信任谁都是问题,因此浏览器厂商们搞出了一个同源策略,就是来防范CSRF(跨站请求伪造)攻击的。
HTTP 协议中的跨域规范
也有网友说,跨域是浏览器的问题,与 http 协议无关。但其实,http 协议中有一个 CORS 机制,下面我们详解一下。
既然跨域是浏览器的限制,HTTP 协议如何解决这个问题?答案就是CORS(跨域资源共享),一套基于 HTTP 头部的授权机制。
核心 HTTP 响应头
服务器通过设置特定的响应头,告诉浏览器:这些源站是我的亲友团,放他们进来。
# 允许的源
Access-Control-Allow-Origin: https://frontend.xttblog.com
# 允许的HTTP方法
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
# 允许的自定义头
Access-Control-Allow-Headers: Content-Type, Authorization
# 是否允许携带Cookie
Access-Control-Allow-Credentials: true
# 预检请求缓存时间(秒)
Access-Control-Max-Age: 86400
看到这里,会不会想起一个问题,那就是如果请求被拦截了,或者说被一个中间商给代理了,那它是不是就有造假的可能?通过设置它想要的特定请求头来骗过浏览器。
是的,这就是中间人攻击,我们这里就不细表了。
预检请求(Preflight)机制
对于可能产生副作用的请求(如 PUT、DELETE 或包含自定义头部),浏览器会先发送一个OPTIONS 预检请求。
类似如下请求。
# 预检请求
OPTIONS /api/data HTTP/1.1
Origin: https://frontend.example.com
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: X-Custom-Header
# 预检响应
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://frontend.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Max-Age: 86400
只有预检通过后,浏览器才会发送实际的请求。这个机制确保了服务器明确知晓并同意跨域操作。这就是为什么浏览器会发生 OPTIONS 请求的原因之一。同时,由于 get 没有副作用,get 请求不会发送 OPTIONS 预检请求。
最佳实践
下面我讲一讲开发中的最佳实践,以及从开发到生产的完整方案。
开发环境
如果是开发环境,快速高效是关键。
可以使用构建工具代理,这也是最推荐的做法。
// Vite配置示例
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://backend.com:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
原理是浏览器请求的是同源地址,/api/data → 代理服务器 → http://xttblog.com:8080/data,完美绕过跨域。
如果不太好使用上面的方法,那也可以使用浏览器的插件进行临时禁用(应急方案)。
安装“Allow CORS”等插件,仅供本地调试使用,切勿依赖此方案解决生产环境问题。
生产环境
生产环境就需要特别注意了,要保证安全与性能并重。
最标准的方案就是后端配置 CORS。切记:
- 永远不要在生产环境使用
Access-Control-Allow-Origin: *配合credentials: true - 始终明确指定允许的源站
- 遵循最小权限原则
如果是微服务,可以在网关层统一处理 CORS 配置,后端服务无需关心跨域逻辑,便于微服务架构下的统一管理。
如果采用了 Nginx 反向代理(架构级方案),那可以配置前后端同源部署。
server {
listen 80;
server_name frontend.example.com;
location /api/ {
proxy_pass http://backend.com:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location / {
root /var/www/frontend;
index index.html;
}
}
这种优势是,由于前后端同源部署,因此能从根本上消除跨域问题。
总结
跨域问题本质上是浏览器安全机制与开发便利性之间的权衡。理解其原理后,你会发现它并非“问题”,而是浏览器为用户安全筑起的一道防火墙。
- 跨域只存在于浏览器,源于同源策略
- CORS 是 HTTP 层面的解决方案,通过响应头授权
未来随着 Web 安全标准的演进,出现了更精细的控制机制。
- COEP/COOP:更严格的跨域隔离策略
- SameSite Cookie:防范 CSRF 攻击的 Cookie 属性
- Private Network Access:限制公网访问内网资源
作为程序员开发者,我们不仅要“解决”跨域,更要理解其安全内涵,在便利性与安全性之间找到最佳平衡点。
参考资料:
- MDN Web Docs – CORS
- W3C CORS Specification

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!
本文原文出处:业余草: » curl、postman、OkHTTP等都能跨域,前端浏览器为什么不能跨域?