Express后端通过Axios无法向React前端传递Cookie求助
问题描述
Express后端设置JWT Cookie后,React前端通过Axios请求无法接收该Cookie,但用Thunder Client测试时Cookie可正常设置。已配置cors、cookie-parser,且开启Chrome第三方Cookie,排查多日未解决。
后端代码
const express = require("express"); // const storiesRouter = require("./routes/storiesRouter") // const postsRouter = require("./routes/postsRouter"); // const usersRouter = require("./routes/usersRouter"); const cors = require("cors"); const cookieParser = require("cookie-parser"); const validator = require("validator"); const bcrypt = require("bcryptjs"); const userSchema = mongoose.Schema({ name: { type: String, required: [true, "Name is required"], }, email: { type: String, required: [true, "Email is required"], unique: true, lowercase: true, validate: [validator.isEmail, "Provide Valid email"], }, img: { data: Buffer, contentType: String, }, role: { type: String, enum: ["user", "lead-guide", "admin"], default: "user", }, password: { type: String, required: [true, "Password is required"], minlength: 8, select: false, }, passwordConfirm: { type: String, required: [true, "Confirm Password is required"], validate: { //Only works on create() or save() validator: function(el) { return el === this.password; }, message: "Password are not same", }, }, passwordChangedAt: { type: Date, }, passwordResetToken: String, passwordResetExpires: Date, active: { type: Boolean, default: true, select: false, }, }); const User = mongoose.model("User", userSchema); const app = express(); // cookieParser middleware app.use(cookieParser()); app.use( cors({ origin: "http://localhost:3001", credentials: true, }) ); app.use(express.json()); app.use("/api/v1/users/login", async (req, res, next) => { console.log("body", req.body); const email = req.body.email; const password = req.body.password; console.log(email, password); if (!email || !password) { res.status(400).json({ status: "fail", message: "Please provide email and password", }); } const user = await User.findOne({ email }).select("+password"); if (!user || !(await user.correctPassword(password, user.password))) { res.status(401).json({ status: "fail", message: "Incorrect email and password", }); } const token = signToken(user._id); req.user = user; console.log(token); res.cookie("jwt", token, { httpOnly: true, secure: false }); res.status(200).json({ status: "success", token, }); console.log("res", res); }); const signToken = (id) => { return jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRES_IN, }); };
前端Axios代码
const LoginFetch = async (methods, dataurl, loginInfo) => { let data = {}; let fetchError = null; await axios( { method: "POST", url: "http://localhost:3000/api/v1/users/login", data: { email: loginInfo.email, password: loginInfo.password }, }, { withCredentials: true, headers: { "Access-Control-Allow-Origin": "*", "Content-Type": "application/json", }, } ) .then((dataRec) => { data = dataRec; }) .catch((err) => { fetchError = err; }); return data; };
解决步骤
1. 修正前端Axios配置参数位置
withCredentials配置被错误放在了第二个参数中,Axios的标准调用格式是axios(configObject),所有配置项需统一放在同一个对象内。修改后的代码:
const LoginFetch = async (methods, dataurl, loginInfo) => { let data = {}; let fetchError = null; await axios({ method: "POST", url: "http://localhost:3000/api/v1/users/login", data: { email: loginInfo.email, password: loginInfo.password }, withCredentials: true, // 移到主配置对象内 headers: { "Content-Type": "application/json", }, }) .then((dataRec) => { data = dataRec; }) .catch((err) => { fetchError = err; }); return data; };
2. 后端补充Cookie的SameSite属性
在设置Cookie时添加sameSite属性,确保跨域场景下Cookie能正常发送:
res.cookie("jwt", token, { httpOnly: true, secure: false, // 开发环境设为false,生产HTTPS环境需改为true sameSite: "Lax" // 开发环境用Lax,严格跨域场景可设为None(需配合secure: true) });
3. 移除前端不必要的请求头
Access-Control-Allow-Origin是后端返回的响应头,前端请求中添加该头无效且可能引发冲突,直接删除。
内容的提问来源于stack exchange,提问作者Aditya Bhatnagar
相关产品推荐
相关产品推荐

