CORS 请求携带身份凭证的方法

配置跨域请求携带 Cookie 和认证信息

问题

默认情况下,跨域请求不会携带 Cookie、HTTP 认证等身份凭证。如何让 CORS 请求携带这些凭证?

解答

需要同时配置客户端和服务端。

客户端配置

// 使用 fetch
fetch('https://api.example.com/data', {
  method: 'GET',
  credentials: 'include' // 关键配置
})

// 使用 XMLHttpRequest
const xhr = new XMLHttpRequest()
xhr.open('GET', 'https://api.example.com/data')
xhr.withCredentials = true // 关键配置
xhr.send()

// 使用 axios
axios.get('https://api.example.com/data', {
  withCredentials: true // 关键配置
})

服务端配置

// Node.js + Express 示例
const express = require('express')
const app = express()

app.use((req, res, next) => {
  // 必须指定具体域名,不能用 *
  res.setHeader('Access-Control-Allow-Origin', 'https://your-site.com')
  
  // 允许携带凭证
  res.setHeader('Access-Control-Allow-Credentials', 'true')
  
  // 允许的请求头
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')
  
  // 允许的方法
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
  
  // 预检请求缓存时间
  res.setHeader('Access-Control-Max-Age', '86400')
  
  // 处理预检请求
  if (req.method === 'OPTIONS') {
    return res.sendStatus(204)
  }
  
  next()
})

动态设置 Origin

// 根据请求来源动态设置,避免硬编码
const allowedOrigins = ['https://site-a.com', 'https://site-b.com']

app.use((req, res, next) => {
  const origin = req.headers.origin
  
  if (allowedOrigins.includes(origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin)
    res.setHeader('Access-Control-Allow-Credentials', 'true')
  }
  
  next()
})

关键点

  • 客户端:fetch 设置 credentials: 'include'XHR 设置 withCredentials: true
  • 服务端:必须设置 Access-Control-Allow-Credentials: true
  • Access-Control-Allow-Origin 不能是 *,必须指定具体域名
  • 凭证包括 Cookie、HTTP 认证信息、TLS 客户端证书
  • 预检请求(OPTIONS)也需要返回正确的 CORS 头