You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

后端因CORS策略无法访问Cookie的问题排查与解决

MERN栈JWT Cookie登录的CORS凭证问题解决

问题描述

基于MERN栈开发React应用,Express+Node.js作为后端,实现Cookie存储JWT的登录系统。前端用axios调用接口,Redux Toolkit管理状态。注册功能正常,但登录时控制台报错:

'The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.'

相关代码

前端API配置

const baseURL="http://localhost:8000";
axios.defaults.withCredentials=true;
const API=axios.create({
    baseURL,
});
export const signIn=(formData)=>API.post('/authentication/signin',formData);
export const login=(formData)=>API.post('/authentication/login',formData);

Redux Thunk调用代码

export const signup=createAsyncThunk('auth/signup',async({formData},{fulfillWithValue,rejectWithValue})=>{
    try{
     const response=await api.login(formData);
     console.log(response.token);
    
    return fulfillWithValue(response.token);
    }catch(err){
        rejectWithValue(err.response.data)
    }
})

后端初始CORS设置

app.use(cors())

后端登录处理函数

export const signUser=catchAsync(async(req,res,next)=>{
  const email=req.body.email;
  const password=req.body.password;
  if(!email||!password){
   return next(new ErrorHandling('You did not entered user name or password',404));
  }
  const user=await User.findOne({email}).select('+password');
  if(!user||!(await user.correctPassword(password,user.password))){
    return next(new ErrorHandling('User name or password are incorrect',400));
  }
    const token=jsonwebtoken.sign({id},process.env.JWT_SECRET,{ 
 expiresIn:process.env.JWT_EXPIRES_IN} );
    const cookieOptions={
        onlyHttp:true
    }
    if(process.env.NODE_ENV=='production'){
        cookieOptions.secure=true;
        cookieOptions.expires=new Date(Date.now()+1000*60)  // 1分钟后过期
    }
    res.cookie('jwt',token,cookieOptions);
    return res.status(statusCode).json({
      status:"success",
      token,
      data: user
      
    })

});

后端index.js初始配置

const app=express();
app.use(express.json());
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(cors())
dotenv.config({path:'./config.env'})
let database=process.env.DATABASE;
const port= process.env.PORT||5000
database=process.env.DATABASE.replace('<password>',process.env.DATABASE_PASSWORD);

app.use('/post',postRoute);
app.use('/user',userRoute);
app.use('/authentication',authRoute);
app.all('*',(req,res,next)=>{
    next(new ErrorHandling("Can't find results check if path is valid",404));
})
app.use(ErrorController)

let conn=mongoose.connect(database,{
 
    useNewUrlParser: true,
    useUnifiedTopology: true
        
}).then(data=>{
    if(data){
        console.log("Successfully connected to server");
    }
    else{
        throw new Error("Unable to connect");
    }
}).catch(err=>{
    console.log(err.message);
})

app.listen(port,()=>{
console.log(`Listening to port ${port}`);
})

package.json片段

{
  "name": "y",
  "version": "1.0.0",
  "description": "Social media blog application",
  "main": "index.js",
  "type": "module",
  "proxy": "http://localhost:3000",
..........
}

解决方法

起初怀疑是CORS配置未开启凭证支持,尝试修改CORS配置:

app.use(cors({
  origin: 'http://localhost:3000', // 匹配前端地址
  credentials: true
}))

但问题仍未解决。最终排查发现是body-parser中间件的顺序错误。

原配置中body-parser放在了cors之前,导致请求先被解析,CORS头无法正确注入响应。将body-parser移到cors之后,调整后的中间件顺序如下:

const app=express();
// 先配置CORS,确保跨域头正确设置
app.use(cors({
  origin: 'http://localhost:3000',
  credentials: true
}));
// 再解析请求体
app.use(express.json());
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
app.use(cookieParser());
// 后续路由、数据库连接等代码保持不变

调整后,CORS先处理跨域请求的响应头,确保Access-Control-Allow-Credentials设为true,之后再解析请求体,axios的withCredentials: true也能正常传递Cookie,登录功能正常工作。

内容的提问来源于stack exchange,提问作者Jogn1522

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 07:05:22