基于Cookie认证的MERN预订项目部署后Cookie无法设置求助
已部署基于Cookie认证的MERN预订项目,接口能正常返回用户信息,但Cookie始终无法在客户端设置。已配置SameSite: none、Secure: true,服务端开启credentials,客户端请求也设置了withCredentials: true,但Cookie仍不存在。以下是相关代码,寻求解决办法:
客户端地址:https://waneem-admin.onrender.com
服务端代码
index.js
import express from 'express' import dotenv from "dotenv" import hotelRouter from './routers/hotel.route.js' import userRouter from './routers/user.route.js' import authRouter from './routers/auth.route.js' import roomRouter from './routers/rooms.route.js' import bookingrouter from './routers/booking.route.js' import cookieParser from 'cookie-parser' import cors from 'cors' import ErrorHandler from './utils/ErrorHandler.js' dotenv.config() export const app = express(); app.use(cookieParser()) //middleware app.use(cors({ origin: "https://waneem-admin.onrender.com", credentials: true, optionSuccessStatus: true, methods: "*" })) app.set("trust proxy", 1) app.use(express.json()) //router app.use('/api/v1/auth', authRouter) app.use('/api/v1/hotels', hotelRouter) app.use('/api/v1/room', roomRouter) app.use('/api/v1/booking', bookingrouter) app.use('/api/v1/user', userRouter) const toke = "Sdfsdfsd" app.get( '/api/v1', (req, res) => { console.log(toke) console.log('here') res.status(200).cookie("access_token", toke, { httpOnly: true, maxAge: 24 * 60 * 60 * 1000, sameSite: "none", secure: true }).send('hello from express') console.log(res) } ) console.log(process.env.ADMIN_URL, process.env.CLIENT_URL) //error middleware app.use(ErrorHandler)
server.js
import { app } from './index.js' import connectDB from './database.js' app.listen(process.env.SERVER_PORT, () => { connectDB() console.log("listening on port 3000") })
Auth控制器(register方法)
import User from "../models/user.model.js" import CreateError from "../utils/CreateError.js" import bcrypt from "bcrypt" import jwt from "jsonwebtoken" import { Sendtoken } from "../utils/Sendtoken.js" export const register = async (req, res, next) => { try { const { password, isAdmin, ...data } = req.body; let isadmin = false; // Verify the token const token = req.cookies.access_token; if (token) { const decoded = jwt.verify(token, process.env.JWT_SECRET); if (decoded && decoded.isAdmin) { isadmin = req.body.isAdmin || false; } } // Check if a user with the same email already exists const existingUser = await User.findOne({ email: data.email }); if (existingUser) { return next(CreateError(400, `User with email ${data.email} already exists`)); } // Hash the password const hashedPassword = await bcrypt.hash(password, 12); // Create a new user const user = new User({ ...data, password: hashedPassword, isAdmin: isadmin, }); // Save the user await user.save(); // Generate and send the token Sendtoken(user, res, 200, "User registered successfully", next); } catch (err) { return next(err); } };
Sendtoken工具函数
import CreateError from "./CreateError.js"; import jwt from "jsonwebtoken" export const Sendtoken = async (user, res, statusCode = 200, message, next) => { try { const token = await jwt.sign({ id: user._id, isAdmin: user.isAdmin }, process.env.JWT_SECRET, { expiresIn: "1d" }) return res.status(statusCode).cookie("access_token", token, { httpOnly: true, maxAge: 24 * 60 * 60 * 1000, sameSite: "none", secure: true }).json({ success: true, message: message || 'login successfull', user: user }) } catch (err) { console.log(err) return next(err) } }
客户端Login组件代码
import React, { useContext, useState } from "react" import { Authcontext } from "../../context/Authcontext.jsx" import axios from "axios" import "./Login.scss" import { useNavigate } from "react-router-dom" const Login = () => { const [credentials, setCredentials] = useState({ email: undefined, password: undefined, }) const { currentUser, loading, error, dispatch } = useContext(Authcontext) const handlechange = (e) => { console.log(e.target.value) return setCredentials((prev) => ({ ...prev, [e.target.id]: e.target.value, })) } console.log(loading) const navigate = useNavigate() const handlesubmit = async (e) => { e.preventDefault() console.log("handlesubmit") console.log("here") dispatch({ type: "START" }) try { const { email, password } = credentials const res = await axios.post(`${import.meta.env.VITE_REACT_SERVER_URL}/api/v1/auth/login`, { email: email, password: password, }, { withCredentials: true, headers: { "Content-Type": "application/json", }, }) dispatch({ type: "SUCCESS", payload: res?.data?.user }) navigate('/') } catch (err) { console.log(err, "by here this error") dispatch({ type: "FAILURE", payload: err.response.data.message }) } } return ( <form className="login" onSubmit={handlesubmit} autoComplete="new-password"> <div className="loginwrapper"> <h1> Login</h1> <input className="logininput" placeholder="username" type="email" id="email" value={credentials.email} onChange={handlechange} /> <input className="logininput" placeholder="password" type="password" autoComplete="new-password" id="password" value={credentials.password} onChange={handlechange} /> <button disabled={loading} className="btn" type="submit"> submit </button> {error && <span className="error"> {error}</span>} <div className="form-bottom"> <span className="forgot">Forgot Password?</span> <span className=" registerbtn" onClick={() => navigate('/register')}>Register here</span></div> </div> </form> ) } export default Login
排查建议
- 检查域名匹配:确认服务端CORS配置的
origin与客户端实际域名完全一致,包括协议、域名、端口(如有),避免多余斜杠或拼写错误。 - 查看响应头:在浏览器Network面板中检查登录/注册接口的响应头,确认
Set-Cookie字段是否存在,且属性(SameSite、Secure、HttpOnly)配置正确。若字段缺失,说明服务端未正确输出Cookie。 - 调整代理信任:服务端已设置
trust proxy:1,可尝试改为trust proxy: true,适配Render的代理环境。 - 添加Cookie域名:在Cookie配置中增加
domain属性,值为服务端主域名(如.your-server-domain.com),适配跨域场景的Cookie存储规则。 - 检查浏览器隐私设置:关闭浏览器"阻止第三方Cookie"选项,跨域场景下该设置会阻止Cookie存储。
- 测试基础接口:先调用服务端
/api/v1GET接口,验证是否能设置Cookie,排除登录/注册逻辑中的问题。 - 全局Axios配置:确保客户端Axios全局开启
withCredentials: true,避免个别请求遗漏配置。
内容的提问来源于stack exchange,提问作者wakai-megumi
相关产品推荐
相关产品推荐

