使用withCredentials遇CORS错误,需保留connect.sid Cookie登录问题
前端通过axios设置withCredentials: true请求http://localhost:3005/api/v1/user接口时触发CORS报错,提示当请求credentials模式为include时,响应头Access-Control-Allow-Origin不能为通配符*。前端已配置请求头,后端已安装并启用cors中间件,设置origin为*且credentials为true,但问题仍存在。移除withCredentials后请求正常,但需要后端获取connect.sid Cookie实现用户登录,求解决办法。
报错信息
Access to XMLHttpRequest at 'http://localhost:3005/api/v1/user' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
Uncaught (in promise) AxiosError {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {…}, request: XMLHttpRequest, …}
前端代码
async function getUser() { const user = await axios.get("http://localhost:3005/api/v1/user", { withCredentials: true, headers: { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' } }); console.log(user) } useEffect(() => { getUser(); }, [])
后端配置
const cors = require('cors') var app = express(); const corsOptions ={ origin:'*', credentials:true, //access-control-allow-credentials:true optionSuccessStatus:200, } app.use(cors(corsOptions))
修正后端CORS配置,将origin改为具体前端域名
开启credentials: true时,Access-Control-Allow-Origin不能用通配符*,必须指定明确的允许来源。修改后端的corsOptions:const corsOptions ={ origin:'http://localhost:3000', // 替换为你的前端实际域名 credentials:true, optionSuccessStatus:200, }若需支持多个域名,可通过函数动态判断:
const allowedOrigins = ['http://localhost:3000', 'https://your-production-domain.com']; const corsOptions = { origin: function (origin, callback) { if (allowedOrigins.includes(origin) || !origin) { callback(null, true) } else { callback(new Error('Not allowed by CORS')) } }, credentials: true, optionSuccessStatus:200 }移除前端请求中的
Access-Control-Allow-Origin请求头Access-Control-Allow-Origin是响应头,无需在前端请求中设置,浏览器会自动处理跨域相关逻辑。修改后的前端代码:async function getUser() { const user = await axios.get("http://localhost:3005/api/v1/user", { withCredentials: true, headers: { 'Content-Type': 'application/json' } }); console.log(user) } useEffect(() => { getUser(); }, [])确保后端Cookie配置正确
若使用express-session,需确保session配置中设置sameSite: 'none'(跨域场景),生产环境需搭配secure: true,开发环境可暂时设为secure: false:app.use(session({ secret: 'your-secret-key', resave: false, saveUninitialized: false, cookie: { sameSite: 'none', secure: process.env.NODE_ENV === 'production', maxAge: 24 * 60 * 60 * 1000 // 1天有效期 } }))
内容的提问来源于stack exchange,提问作者Running moments

