Express中已设置Cookie但req.cookies无法获取JWT的问题解决
我使用Express作为后端、Next.js作为前端开发应用。登录后浏览器已成功设置名为jwt的Cookie,但在protect中间件中通过req.cookies?.jwt获取到的值为undefined,无法完成用户权限验证。相关代码如下:
相关代码
protect中间件
const protect = asyncHandler(async (req, res, next) => { let token; token=req.cookies?.jwt if (token) { try { const decoded = jwt.verify(token, process.env.JWT_SECRET); console.log(decoded) req.user = await prisma.user.findFirst({ where: { email: decoded.email, }, }); next(); } catch (err) { res.status(401); throw new Error(`Not Authorized, Invalid Token`); } } else { res.status(401); throw new Error(`Not Authorized, No Token`); } });
generateToken函数
const generateToken = (res, email) => { console.log('email form generate',email) try { const token = jwt.sign({ email }, process.env.JWT_SECRET, { expiresIn: "30d", }); console.log(token) res.cookie("jwt", token, { httpOnly: true, secure: process.env.NODE_ENV==="Production", sameSite: process.env.NODE_ENV==="Production"?"None":"Strict", maxAge: 30 * 24 * 60 * 60 * 1000, }); } catch (error) { res.status(500); throw new Error(`Issue With Assiging JWT`); } };
用户控制器
const loginUser = asyncHandler(async (req, res) => { const { email, password } = req.body; if (!email || !password) throw new Error(`Provide Valid User Details`); const validUser = await prisma.user.findFirst({ where: { email:email, }, }); if (!validUser) throw new Error(`Invalid User Details`); const validPassword = await compareHashPassword(password, validUser.password); if (validUser && validPassword) { generateToken(res, validUser.email); const data = { email: validUser.email, isAdmin: validUser.isAdmin, }; res.status(200).json({ data, message: `Login Successfull`, }); } else { res.status(400).send({message:"Invalid User Information"}); throw new Error(`Invalid User Details`); } }); const getUserProfile = asyncHandler(async (req, res) => { console.log('user',req.user) try{ const data = { email: req.user.email, isAdmin: req.user.isAdmin, }; res.status(200).json({ data }); }catch(error){ res.status(401).send({message:"UnAuthorized User"}) } });
用户路由
// Login /api/users/signin router.route("/signin").post(loginUser); // Logout /api/users/logout router.route("/logout").post(logoutUser); //Get profile router.get("/profile",protect, getUserProfile);
原因分析及修复方案
1. 未配置cookie-parser中间件
Express默认不会解析请求中的Cookie,必须通过cookie-parser中间件处理,否则req.cookies会是undefined。
修复:
- 安装依赖:
npm install cookie-parser
- 在Express入口文件(如
server.js)中引入并启用:
const cookieParser = require('cookie-parser'); // 必须在路由配置之前添加 app.use(cookieParser());
2. 前端请求未携带Credentials
Next.js发送跨域请求时,默认不会携带Cookie,需显式开启credentials选项。
修复:
- 使用
fetch时:
fetch('/api/users/profile', { method: 'GET', credentials: 'include', })
- 使用
axios时:
axios.get('/api/users/profile', { withCredentials: true, })
3. SameSite配置不匹配开发环境
开发环境下sameSite设为Strict,若前后端运行在不同端口(如前端3000、后端5000),属于跨源请求,Strict会阻止Cookie携带。
修复:
修改generateToken中的SameSite配置,开发环境改为Lax:
res.cookie("jwt", token, { httpOnly: true, secure: process.env.NODE_ENV === "Production", sameSite: process.env.NODE_ENV === "Production" ? "None" : "Lax", maxAge: 30 * 24 * 60 * 60 * 1000, });
注意:
SameSite=None必须配合secure: true使用,而开发环境通常是HTTP协议,所以不能用None,否则浏览器会拒绝设置Cookie。
4. CORS未允许Credentials
前后端跨域时,Express需配置CORS允许携带Cookie。
修复:
- 安装
cors依赖:
npm install cors
- 配置CORS:
const cors = require('cors'); app.use(cors({ origin: process.env.FRONTEND_URL || 'http://localhost:3000', // 你的前端地址 credentials: true, }));
验证步骤
- 登录后,在浏览器开发者工具Application > Cookies中确认
jwtCookie存在,且Domain、Path配置正确。 - 发送
/api/users/profile请求时,查看Network > 请求头是否包含Cookie: jwt=xxx。 - 在
protect中间件开头添加console.log(req.cookies),确认是否能获取到Cookie对象。
内容的提问来源于stack exchange,提问作者iftekhar
相关产品推荐
相关产品推荐

