跨域请求携带 Cookie 的完整真相:一次说清所有误区


1. 前言:为什么又写这个话题?

基于之前我发的一篇文章Axios 如何跨域携带 Cookie?Axios 如何跨域携带 Cookie? 一、什么是跨域?核心是"同源策略" 1 - 掘金。 重新思考整理后发现,网上 90% 的文章只告诉你"前端加 withCredentials: true,后端加 Access-Control-Allow-Credentials: true 就行"。但当你真去调试时,却发现:

  • 第一次 GET 请求 根本没带 Cookie
  • 控制台报错:Access-Control-Allow-Origin 不能用 *
  • POST 居然发了 两次 请求?

本文用浏览器视角一次性讲透。


角色 职责
浏览器 唯一裁判:决定是否发送/接受 Cookie
前端 通过 withCredentials: true 告诉浏览器"我想带"
后端 通过响应头告诉浏览器"我允许"

⚠️ 只要浏览器不点头,即使后端返回 200,前端也拿不到数据


3. 场景一:简单请求(GET/HEAD,无自定义头)

3.1 代码示例

csharp 复制代码
// 前端:a.com
axios.get('https://b.com/api', { withCredentials: true });

3.2 真实流程

  1. 浏览器先裸发

    • Origin: https://a.com
    • 不带 Cookie(无论后端是否允许)
    • 无预检(preflight)
  2. 后端返回

    yaml 复制代码
    Access-Control-Allow-Origin: https://a.com
    Access-Control-Allow-Credentials: true
  3. 浏览器检查通过后

    • 把响应交给前端
    • 缓存标记:下次同域请求可带 Cookie
  4. 第二次请求

    • 浏览器自动带上 Cookie

3.3 结论

第几次请求 是否带 Cookie 前端能否拿到数据
第 1 次 ❌ 不带 ✅ 能(后端已正确配置)
第 2 次及以后 ✅ 带 ✅ 能

所以第一次不会"失败",只是不带 Cookie。


4. 场景二:非简单请求(POST/PUT/DELETE 等)

4.1 触发条件

  • 自定义头(如 Authorization
  • Content-Type 不是 application/x-www-form-urlencodedmultipart/form-datatext/plain

4.2 代码示例

php 复制代码
axios.post('https://b.com/api', { foo: 1 }, {
  withCredentials: true,
  headers: { 'Content-Type': 'application/json' }
});

4.3 真实流程(两次往返)

  1. 预检 OPTIONS

    makefile 复制代码
    OPTIONS /api HTTP/1.1
    Origin: https://a.com
    Access-Control-Request-Method: POST
    Access-Control-Request-Headers: content-type
    • 不带 Cookie

    • 后端需返回:

      yaml 复制代码
      Access-Control-Allow-Origin: https://a.com
      Access-Control-Allow-Credentials: true
      Access-Control-Allow-Methods: POST
      Access-Control-Allow-Headers: Content-Type
  2. 实际业务请求

    • 此时才带 Cookie
    • 后端再次返回相同 CORS 头

4.4 时间线图

markdown 复制代码
浏览器 ──OPTIONS──> 后端
       <─200 OK──  (预检通过)

浏览器 ──POST+Cookie──> 后端
       <─200 OK+数据──

5. 常见坑与排查清单

现象 原因 解决
控制台报错 wildcard * 后端返回 Access-Control-Allow-Origin: * 改成具体域名
第一次 GET 没 Cookie 浏览器策略:第一次永远不带 无需解决,第二次会带
POST 发两次 预检 OPTIONS 正常行为
本地 http://localhost 调不通 Cookie 需 Secure 属性 用 https 或改 Cookie 设置

6. 后端配置示例

Node.js(Express)

php 复制代码
const cors = require('cors');
app.use(cors({
  origin: 'https://a.com', // 不能是 *
  credentials: true
}));

Nginx

ini 复制代码
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;

7. 一句话总结

跨域携带 Cookie 的钥匙始终握在浏览器手里:
第一次 GET 永远不带 Cookie,后端点头后,后续才带;
非简单请求需预检,真正业务请求第二次才带 Cookie。


8. 参考资料


如果本文帮你理清了思路,点个 ⭐ 吧!

相关推荐
qq_589666057 小时前
TypeScript 完整入门教程
前端·javascript·typescript
用户0595401744610 小时前
LLM对话记忆测试踩坑实录:手工回归30分钟,自动化后2分钟发现3个隐藏Bug
前端·css
Ashley的成长之路11 小时前
前端性能优化实战手册·第2篇:资源加载策略全解
前端·性能优化·资源加载·http/3·性能优化实战·资源加载优化
浅水壁虎11 小时前
vue基础(第二章 )
前端·javascript·vue.js
界面开发小八哥11 小时前
界面控件DevExtreme v26.1新版亮点——支持Angular 22
前端·javascript·angular.js·devexpress·ui开发·devextreme
Getflare11 小时前
前端 + UI 设计 + AI:这不是三个工种,是一个新三角能力模型(附自检清单)
前端·人工智能·ui
oil欧哟12 小时前
我做了一个 Vibe Coding 术语学习站:VibeHub
前端·ai·agent·独立开发·vibe coding
审小匠OpenCPAi12 小时前
银行流水核查怎么自动化?单边匹配、双向勾稽与图聚类异常检测的工程对比
java·前端·人工智能·python·审计
Revolution6112 小时前
一个公共表格组件,是怎么一步步失控的
前端·前端工程化