浏览器拒绝跨域AJAX请求是因同源策略强制限制,协议、域名、端口任一不同即拦截;而<img>等标签属只读通道,不读响应体故不触发CORS校验。

浏览器直接拒绝跨域 AJAX 请求,不是代码写错了,是它本该如此——同源策略在起作用。只要协议、域名、端口任一不同,fetch 或 XMLHttpRequest 就会被拦截,控制台报错里通常带 Access-Control-Allow-Origin 缺失或不匹配。
为什么 <img> 和 <script> 不报错,但 fetch 会?
HTML 标签如 <img>、<script>、<link> 天然支持跨域加载资源,这是浏览器早期就放开的“只读通道”。它们不涉及敏感数据读取,所以无需预检、也不校验响应头。
而 fetch 或 XMLHttpRequest 默认试图读取响应体内容(比如 JSON),这就触发了完整的 CORS 流程:先发一个 OPTIONS 预检请求,再根据服务器返回的 Access-Control-Allow-Origin 等头决定是否放行真实请求。
- 如果你只是显示图片,用
<img src="https://api.example.com/photo.jpg">完全没问题 - 但你想用 JS 读取这张图的宽高或像素数据?必须加
crossorigin="anonymous",且服务端要返回Access-Control-Allow-Origin: * -
<script src="https://cdn.jsdelivr.net/npm/vue@3">可以直接运行,但你无法通过fetch去拿这个 URL 的原始文本并eval它——后者会被拦住
fetch 跨域失败时,控制台典型错误长什么样?
打开 DevTools → Console,常见错误信息包括:
立即学习“前端免费学习笔记(深入)”;
Blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.Blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.-
Failed to fetch: TypeError: Failed to fetch(底层原因还是 CORS)
注意:这些错误不会出现在 Network 面板的响应体里,而是直接中断 JS 执行流。如果你没在 catch 中处理,请求就静默失败了。
排查顺序建议:
– 先看 Network → Headers → Response Headers 里有没有 Access-Control-Allow-Origin
– 再确认请求是否带了 credentials: 'include',这时服务端不能返回 *,必须指定具体域名
– 最后检查预检(OPTIONS)是否被 404 或 405 拦截——有些后端框架默认不处理 OPTIONS
前端能绕过 CORS 吗?哪些方案真有用,哪些只是幻觉?
纯前端(即不改服务端、不加代理、不换部署方式)条件下,能真正解决跨域读取响应内容的方案极少。以下判断基于当前(2026 年)主流浏览器行为:
- JSONP:仅适用于 GET,且服务端必须支持回调参数(如
?callback=xxx)。现代 API 很少提供,axios已移除原生 JSONP 支持 -
postMessage:只能用于同页面内 iframe 通信,不能用来调第三方 API - 改
document.domain:仅限子域场景(如a.example.com↔b.example.com),且现代浏览器对它的限制越来越严 - CORS 配置本身不是前端能“做”的事——它必须由服务端响应头声明。前端唯一可控的是发起请求时的选项,比如:
credentials: 'include'、mode: 'cors'(fetch默认就是)、headers是否合法(如不能手动设Cookie)
真正落地的解法往往是组合动作:开发阶段用本地代理(如 Vite 的 server.proxy),上线后靠后端配好 Access-Control-Allow-Origin 和 Access-Control-Allow-Methods;若你调的是别人家的 API,又没权限改他们服务端,那就只能确认对方是否开放 CORS,否则只能走自己搭的中转代理。
容易被忽略的细节:带 Cookie 的跨域请求为什么总失败?
一旦你在 fetch 中写了 credentials: 'include',或在 XMLHttpRequest 中设了 xhr.withCredentials = true,规则立刻变严格:
- 服务端响应头
Access-Control-Allow-Origin不能再是*,必须明确写出请求来源(如https://your-app.com) - 服务端还得额外返回
Access-Control-Allow-Credentials: true - 如果用了通配符域名(如
*.example.com),浏览器不认——它只接受完整域名或null - 前端请求头里不能手动设置
Cookie字段(浏览器自动注入),否则预检直接被拒
这个组合条件漏掉任意一项,控制台都会报错,而且错误提示可能指向不同位置。最稳妥的做法是:先去掉 credentials 测试能否拿到响应体;确认基础 CORS 通了,再逐步加上认证逻辑。



















