跨域与 CORS 速查
同源策略到底在防什么、什么样的请求会触发预检、Access-Control-* 头部怎么配才不会报错,以及几个必踩的坑。
跨域报错几乎是每个前端都会碰到的第一个「玄学问题」:接口用工具能调通,浏览器里就是不行。原因在于同源策略——浏览器主动限制网页去读取其他源的响应,这是一道安全闸门,而不是服务器坏了。
CORS(跨源资源共享)是这道闸门的官方放行机制:由服务器在响应头里明确声明「我允许哪些来源读我的数据」。所以跨域问题几乎总是要在服务端改,前端改不了。
1同源策略:三个维度必须全同
判断两个地址是否同源,只看「协议 + 主机 + 端口」三件事,任意一项不同就是跨源。路径与查询参数不参与判断。
| 当前页面 | 请求目标 | 是否同源 | 原因 |
|---|---|---|---|
https://a.com | https://a.com/api | 同源 | 协议、主机、端口全同,路径不同不影响 |
https://a.com | http://a.com/api | 跨源 | 协议不同(https 与 http) |
https://a.com | https://b.com/api | 跨源 | 主机不同 |
https://a.com | https://a.com:8080/api | 跨源 | 端口不同(默认 443 与 8080) |
https://a.com | https://api.a.com | 跨源 | 子域名也算不同主机 |
https://a.com | https://a.com:443/api | 同源 | 省略端口时按协议默认端口补齐,与显式 443 等价 |
| 页面打开方式 | file:// 协议 | 跨源 | 本地直接打开 HTML 时源为空,很多接口会因此被拦 |
同源策略限制的是「网页读取响应内容」,不是「请求发不出去」。跨域请求实际已经到达服务器并执行了(除非是预检被拒),只是响应内容不给页面读。所以「跨域报错但服务端日志有记录」是完全正常的。
2简单请求与预检请求
CORS 分两种处理方式,判断依据是「请求本身有多特殊」。越简单的请求越少一次往返。
| 类别 | 触发条件 | 流程 | 代价 |
|---|---|---|---|
| 简单请求 | 方法为 GET / HEAD / POST,且头部仅限安全列表字段,Content-Type 仅限表单类三种 | 直接发出,浏览器看响应头决定是否放行 | 一次往返 |
| 预检请求 | 方法为 PUT / DELETE / PATCH 等,或 Content-Type: application/json,或带了自定义头部 | 先用 OPTIONS 问服务器允不允许,通过后才发真实请求 | 多一次往返 |
| 带凭证请求 | 设置了 withCredentials 或 credentials: include | 额外要求 Allow-Origin 不能是 *,且需 Allow-Credentials | 配置更严格 |
| 预检缓存 | 服务器返回 Access-Control-Max-Age | 在有效期内同源的同类请求不再重复预检 | 减少 OPTIONS 次数 |
| 被拒之后 | 预检未通过 | 浏览器直接拦截,真实请求不会发出 | 前端只看到 CORS 报错,服务端看不到真实请求 |
开发时最常见的跨域场景是「本地 `localhost:3000` 调线上 `api.xxx.com`」。这类问题最简单的解法是开发服务器配一层代理,让请求同源发出;上线后同域部署则根本不存在跨域。比在生产环境放开 `*` 安全得多。
3CORS 响应头对照
服务器通过这些响应头声明放行规则。注意「请求头」与「响应头」的区别:Origin 是浏览器发出的,其余都是服务器返回的。
| 头部 | 作用 | 取值说明 |
|---|---|---|
Access-Control-Allow-Origin | 允许哪些源读取响应 | 可以是具体的源或 *;带凭证时不能用 * |
Access-Control-Allow-Methods | 允许哪些方法 | 如 GET, POST, PUT, DELETE, OPTIONS |
Access-Control-Allow-Headers | 允许哪些请求头 | 自定义头必须在这里列出,否则预检失败 |
Access-Control-Allow-Credentials | 是否允许携带凭证 | 设为 true 时 Allow-Origin 必须是具体源 |
Access-Control-Max-Age | 预检结果缓存多久 | 单位秒,减少 OPTIONS 请求次数 |
Access-Control-Expose-Headers | 允许页面读取哪些自定义响应头 | 默认只能读少数几个基础头 |
Vary: Origin | 告诉缓存按 Origin 区分副本 | 多源动态返回时必须加,否则 CDN 会串源 |
如果 `Allow-Origin` 需要按请求的 `Origin` 动态回显(比如支持多个白名单域名),务必同时返回 `Vary: Origin`。否则 CDN 或代理可能把给 A 站的响应缓存下来发给 B 站,造成安全与功能双重问题。
4常见跨域报错对照
浏览器只在控制台给一行报错,成因却各不相同。看关键短语就能定位。
- `No 'Access-Control-Allow-Origin' header`
- 服务端没有返回这个头。检查是否真的配置了 CORS,以及请求是否真的打到了预期的服务
- `credentials flag is true, but Allow-Origin is *`
- 带凭证时不能用通配符。把
Allow-Origin改成回显具体的Origin - `does not pass access control check`(预检失败)
Allow-Methods或Allow-Headers没覆盖实际用到的方法或头。补齐即可- `Response to preflight request doesn't pass`
OPTIONS请求没被正确处理。不少框架需要显式放行OPTIONS路由,或中间件顺序不对- `Redirect is not allowed for a preflight request`
- 预检不支持 302 / 301 跳转。把 CORS 处理放在跳转之前
- 浏览器正常但工具正常
- 命令行工具不受同源策略约束,所以「Postman 能调通」不能说明浏览器也能
看完就能用的站内工具
全部工具总览 →生成 CORS 跨域响应头配置,勾选允许的请求方法与来源,输出完整的访问控制头与预检请求响应示例,并提示通配符与凭证的非法组合。
在线生成网站安全响应头配置,包含 HSTS、X-Frame-Options、X-Content-Type-Options、Referrer-Policy 等,输出 Nginx 与 Apache 配置片段
在线扫描页面源码或链接列表里的 http:// 明文资源,按主动型与被动型分类,给出被拦截风险清单与一键升级结果
在线生成 Set-Cookie 响应头,配置 SameSite、Secure、HttpOnly、Max-Age 与 __Host- 前缀,并自动校验属性冲突
关于「跨域与 CORS 速查」的常见问题
什么是同源策略,为什么要有它?
同源策略是浏览器的安全机制:一个网页只能读取与它「协议、主机、端口完全一致」的源的响应内容。它的作用是防止恶意页面在用户已登录某个网站的情况下,偷偷去读取那个网站的数据——比如一个钓鱼页面用用户浏览器里的登录状态去请求网银接口,如果没有同源策略,它就能读到余额信息。这个策略限制的是「读取响应」,不是「发出请求」,所以跨域请求实际会到达服务器,只是响应内容不给当前页面读。
为什么我的请求会多发一次 OPTIONS?
这是 CORS 的预检机制。当请求不属于「简单请求」时——例如用了 PUT / DELETE 方法、Content-Type 是 application/json、或带了自定义请求头——浏览器会先发一个 OPTIONS 请求询问服务器「允许这个源用这个方法、带这些头吗」,得到肯定答复后才发真正的请求。所以你会看到两条记录。解决办法有两个:一是服务器返回 Access-Control-Max-Age,让浏览器缓存预检结果,减少重复的 OPTIONS;二是把请求改造成简单请求(如用表单编码),但不是所有场景都可行。
带 Cookie 的跨域请求为什么总是失败?
因为带凭证的跨域有额外的硬性限制。首先 Access-Control-Allow-Credentials 必须显式设为 true;其次 Access-Control-Allow-Origin 不能是通配符 *,必须回显请求的具体 Origin 值(或精确匹配白名单);另外前端也要显式开启凭证发送(fetch 里设 credentials: include,或 XHR 里设 withCredentials = true)。这三点缺任何一个都会失败。还要注意 Cookie 自身的 SameSite 属性也可能拦下跨站请求,如果 Cookie 设了 SameSite=Strict,跨站场景下根本不会被带上。
跨域问题该在前端解决还是后端解决?
本质上必须在服务端解决,因为 CORS 是服务器通过响应头声明放行规则的,前端改不了服务端。前端能做的主要是规避:开发阶段配置开发服务器代理,让请求从同源发出,从而不触发跨域;或者把请求发到自己的后端,由后端再去调用第三方接口(服务端之间不受同源策略约束)。上线阶段最稳的是应用与接口同域部署,或至少同主域,从根本上避免跨域。不建议在生产环境把 Allow-Origin 放开成 *,也不建议用把浏览器安全策略关掉的方式「解决」问题。
继续查:相关内容
全部速查 →内容说明:本页速查数据由本站自行整理,事实性内容以对应官方规范与文档为准,未复制第三方速查表或百科的表述。数据最后核对日期:2026-10-05。若发现错误或已更新的标准,欢迎通过页脚反馈入口告知。
速查在线工具箱