跨域请求携带 Cookie 鉴权失败 Access-Control 配置怎么改?

文章导读
核心解决方案:跨域携带 Cookie 失败通常是因为 CORS 配置不完整。必须同时修改前端请求配置和服务端响应头,且 Access-Control-Allow-Origin 不能为星号 *。
📋 目录
  1. 前端请求配置
  2. 后端服务配置
  3. Nginx 反向代理配置
  4. 验证与排查
  5. 常见坑与注意事项
A A

核心解决方案:跨域携带 Cookie 失败通常是因为 CORS 配置不完整。必须同时修改前端请求配置和服务端响应头,且 Access-Control-Allow-Origin 不能为星号 *

  • 前端:请求中显式开启 withCredentialscredentials: include
  • 后端:响应头指定具体域名,设置 Access-Control-Allow-Credentials: true
  • 验证:浏览器开发者工具 Network 面板确认响应头生效

前端请求配置

浏览器默认跨域请求不携带 Cookie,需在代码中显式声明。以下是常见请求库的配置方式:

1. Fetch API

fetch("https://api.example.com/data", {
  method: "GET",
  credentials: "include", // 关键配置:允许携带 Cookie
  headers: {
    "Content-Type": "application/json"
  }
})
.then(response => response.json())
.catch(error => console.error("Error:", error));

2. Axios

// 全局配置
axios.defaults.withCredentials = true;

// 或单次请求配置
axios.get("https://api.example.com/data", {
  withCredentials: true // 关键配置
});

后端服务配置

服务端需明确允许特定源携带凭证。直接使用 * 会导致浏览器拒绝携带 Cookie。

跨域请求携带 Cookie 鉴权失败 Access-Control 配置怎么改?

1. Node.js (Express + cors 中间件)

推荐使用 cors 中间件,避免手动拼接 Header 出错。注意 Origin 需校验白名单,不要直接反射请求头。

跨域请求携带 Cookie 鉴权失败 Access-Control 配置怎么改?
const cors = require("cors");
const express = require("express");
const app = express();

const allowedOrigins = ["https://your-frontend.com", "https://www.your-frontend.com"];

app.use(cors({
  origin: function (origin, callback) {
    // 安全校验:仅在白名单内允许,或允许无 origin (如 Postman/本地)
    if (!origin || allowedOrigins.indexOf(origin) !== -1) {
      callback(null, true);
    } else {
      callback(new Error("Not allowed by CORS"));
    }
  },
  credentials: true, // 允许携带凭证
  methods: ["GET", "POST", "OPTIONS"],
  allowedHeaders: ["Content-Type", "Authorization"]
}));

app.listen(3000);

2. 手动设置响应头 (通用逻辑)

若不使用中间件,需确保 OPTIONS 预检请求也返回正确 Header。

// 伪代码示例
response.setHeader("Access-Control-Allow-Origin", "https://your-frontend.com");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");

if (request.method === "OPTIONS") {
  return response.send(204); // 预检请求直接返回
}

Nginx 反向代理配置

若在 Nginx 层处理 CORS,需注意 add_header 默认只在 200/204/301/302 状态码生效,建议添加 always 参数,并单独处理 OPTIONS 请求。

跨域请求携带 Cookie 鉴权失败 Access-Control 配置怎么改?
server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://backend_server;

        # 指定具体域名,禁止使用 *
        add_header Access-Control-Allow-Origin "https://your-frontend.com" always;
        add_header Access-Control-Allow-Credentials true always;
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
        add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;

        # 处理预检请求
        if ($request_method = "OPTIONS") {
            add_header Access-Control-Allow-Origin "https://your-frontend.com" always;
            add_header Access-Control-Allow-Credentials true always;
            add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
            add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
            return 204;
        }
    }
}

验证与排查

配置完成后,按以下步骤验证是否生效:

  1. 打开开发者工具:浏览器按 F12,进入 Network 面板。
  2. 触发请求:刷新页面或点击按钮触发跨域请求。
  3. 检查预检请求:查看是否有 OPTIONS 请求,状态码应为 204 或 200。
  4. 检查响应头:点击正式请求,查看 Response Headers 是否包含:
    • Access-Control-Allow-Credentials: true
    • Access-Control-Allow-Origin: https://your-frontend.com (必须与当前页面域名一致)
  5. 检查 Cookie:确认请求头 Request Headers 中是否包含 Cookie 字段。

常见坑与注意事项

  • Origin 不能为星号:Access-Control-Allow-Credentialstrue 时,Access-Control-Allow-Origin 严禁设置为 *,否则浏览器会拦截。
  • Cookie SameSite 属性:跨域场景下,Cookie 的 SameSite 属性需设置为 None,且必须配合 Secure 属性(即必须在 HTTPS 环境下)。
  • 动态 Origin 安全风险:不要直接将请求头中的 Origin 反射回响应头,应维护一个白名单进行匹配,防止开放授权漏洞。
  • 缓存问题:浏览器可能缓存了错误的 CORS 响应头。验证时尝试硬刷新 (Ctrl+F5) 或清除缓存,必要时在 Nginx 中关闭 OPTIONS 缓存。
  • 端口一致性问题:域名相同但端口不同(如 80 与 8080)也属于跨域,需同样配置 CORS。