Node.js+React双用户JWT认证异常:Market用户验证失败
问题:Market用户Token验证失败排查
我基于Node.js API后端和React.js前端开发项目,支持User和Market两类用户登录,对应MongoDB不同文档模型。User用户认证流程正常,但Market用户Token生成成功却无法通过验证,登录时控制台输出“No token jwt2”。
相关代码文件
server.js
const express = require('express'); const bodyParser = require("body-parser"); const cookieParser = require("cookie-parser"); const cors = require('cors'); const app = express(); const {checkUser, requireAuth, checkMarket, requireAuthMarket} = require('./middleware/auth.middleware'); require('dotenv').config({path: './config/.env'}); require('./config/db'); const marketRoutes = require("./routes/market.routes"); const marketpostRoutes = require("./routes/marketpost.routes"); const postRoutes = require('./routes/post.routes'); const userRoutes = require('./routes/user.routes'); const axios = require("axios"); const corsOptions = { origin: process.env.CLIENT_URL, credentials: true, 'allowedHeaders': ['sessionId', 'Content-Type'], 'exposedHeaders': ['sessionId'], 'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', 'preflightContinue': false } app.use(cors(corsOptions)); app.use(express.urlencoded({ extended: true })); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(cookieParser()); // 令牌验证路由 app.get('*', checkMarket); app.get('/jwt2id', requireAuthMarket, (req, res) => { res.status(200).send(res.locals.market._id) }); app.get('*', checkUser); app.get('/jwtid', requireAuth, (req, res) => { res.status(200).send(res.locals.user._id) }); // 业务路由 app.use('/api/user', userRoutes); app.use('/api/post', postRoutes); app.use('/api/marketpost', marketpostRoutes); app.use('/api/market', marketRoutes); // 启动服务器 app.listen(process.env.PORT, () => { console.log("le server a démarré au port: " + process.env.PORT); })
authuser.js
const UserModel = require('../models/user.model.js'); const jwt = require('jsonwebtoken'); const { signUpErrors, signInErrors } = require('../utils/errors.utils'); const maxAge = 3 * 24 * 60 * 60 * 1000; const createToken = (id) => { return jwt.sign({id}, process.env.TOKEN_SECRET, { expiresIn: maxAge }) }; module.exports.signUp = async (req, res) => { const { nom, pseudo, email, password, phoneNumber } = req.body; try { const user = await UserModel.create({ nom, pseudo, email, password, phoneNumber }); res.status(201).json({ user: user._id }); } catch (err) { const errors = signUpErrors(err); res.status(200).json({ errors }); } }; module.exports.signIn = async (req, res) => { const { email, password } = req.body try { const user = await UserModel.login(email, password); const token = createToken(user._id); res.cookie('jwt', token, { httpOnly: true, maxAge }); res.status(200).json({ user: user._id}) } catch (err){ const errors = signInErrors(err); res.status(200).json({ errors }); } } module.exports.logout = (req, res) => { res.cookie('jwt', '', { maxAge: 1 }); res.redirect('/'); }
authMarket.js
const MarketModel = require('../models/market.model.js'); const jwtmarket = require('jsonwebtoken'); const { signUpErrors, signInErrors } = require('../utils/errors.utils'); const maxAge = 2 * 24 * 60 * 60 * 1000; const createToken = (id) => { return jwtmarket.sign({id}, process.env.TOKEN_SECRET_MARKET, { expiresIn: maxAge }) }; module.exports.signUp = async (req, res) => { const { nom, email, password, phoneNumber} = req.body; try { const market = await MarketModel.create({ nom, email, password, phoneNumber}); res.status(201).json({ market: market._id }); } catch (err) { const errors = signUpErrors(err); res.status(200).json({ errors }); } }; module.exports.signIn = async (req, res) => { const { email, password } = req.body; try { const market = await MarketModel.login(email, password); const tokenk = createToken(market._id); res.cookie('jwt2', tokenk, { httpOnly: true, maxAge }); res.status(200).json({ market: market._id}) console.log(tokenk); } catch (err){ const errors = signInErrors(err); res.status(200).json({ errors }); } } module.exports.logout = (req, res) => { res.cookie('jwt2', '', { maxAge: 1 }); res.redirect('/'); }
authmiddleware.js
const UserModel = require("../models/user.model"); const MarketModel = require("../models/market.model"); const jwt = require("jsonwebtoken"); const jwtmarket = require("jsonwebtoken"); module.exports.checkUser = (req, res, next) => { const token = req.cookies.jwt; if (token) { jwt.verify(token, process.env.TOKEN_SECRET, async (err, decodedToken) => { if (err) { res.locals.user = null; next(); } else { let user = await UserModel.findById(decodedToken.id); res.locals.user = user; next(); } }); } else { res.locals.user = null; next(); } }; module.exports.checkMarket = (req, res, next) => { const tokenk = req.cookies.jwtmarket; if (tokenk) { jwtmarket.verify(tokenk, process.env.TOKEN_SECRET_MARKET, async (err, decodedToken) => { if (err) { res.locals.market = null; next(); } else { let market = await MarketModel.findById(decodedToken.id); res.locals.market = market; next(); } }); } else { res.locals.market = null; next(); } }; module.exports.requireAuth = (req, res, next) => { const token = req.cookies.jwt; if (token) { jwt.verify(token, process.env.TOKEN_SECRET, async (err, decodedToken) => { if (err) { console.log(err); res.status(401).json({ message: "Unauthorized" }); } else { console.log(decodedToken.id); next(); } }); } else { console.log("No token"); res.status(401).json({ message: "Unauthorized" }); } }; module.exports.requireAuthMarket = (req, res, next) => { const tokenk = req.cookies.jwtmarket; if (tokenk) { jwtmarket.verify(tokenk, process.env.TOKEN_SECRET_MARKET, async (err, decodedToken) => { if (err) { console.log(err); res.status(401).json({ message: "Unauthorized" }); } else { console.log(decodedToken.id); next(); } }); } else { console.log("No token jwt2"); res.status(401).json({ message: "Unauthorized" }); } };
App.js
import React, { useEffect, useState } from 'react'; import Routes from "./components/Routes/index"; import { UidContext } from './components/AppContext'; import { MidContext } from './components/AppContext'; import axios from 'axios'; import { useDispatch } from 'react-redux'; import { getUser } from './actions/user.actions'; import { getMarket } from './actions/market.actions'; import MyRoutes from './components/Routes/MyRoutes'; const App = () => { const [uid,setUid] = useState(null); const dispatch = useDispatch(); const [mid,setMid] = useState(null); useEffect(() => { const fetchToken = async () => { await axios({ method: "get", url: `${process.env.REACT_APP_API_URL}jwtid`, withCredentials: true, }) .then((res) => { setUid(res.data); }) .catch((err) => console.log("No token/jeton")); }; fetchToken(); if (uid) dispatch(getUser(uid)); }, [uid,dispatch]); useEffect(() => { const fetchToken = async () => { await axios({ method: "get", url: `${process.env.REACT_APP_API_URL}jwt2id`, withCredentials: true, }) .then((res) => { setMid(res.data); }) .catch((err) => console.log("No token/jeton")); }; fetchToken(); if (mid) dispatch(getMarket(mid)); }, [mid, dispatch]); console.log(mid+"trueeeeeee"); return ( <> <UidContext.Provider value={uid}> <MidContext.Provider value={mid}> <Routes /> </MidContext.Provider> </UidContext.Provider> <MidContext.Provider value={mid}> <MyRoutes /> </MidContext.Provider> </> ); }; export default App;
问题根源与修复方案
核心问题:Cookie名称不匹配
- 在
authMarket.js的signIn方法中,设置的Cookie名称是jwt2:res.cookie('jwt2', tokenk, { httpOnly: true, maxAge }); - 但在
authmiddleware.js的checkMarket和requireAuthMarket方法中,读取的Cookie名称是jwtmarket:const tokenk = req.cookies.jwtmarket;
两者名称不一致,导致后端无法读取到正确的Market用户Token,从而输出“No token jwt2”。
修复步骤
- 统一Cookie名称
修改authmiddleware.js中的checkMarket和requireAuthMarket方法,将读取的Cookie名称改为jwt2:
// checkMarket方法 const tokenk = req.cookies.jwt2; // requireAuthMarket方法 const tokenk = req.cookies.jwt2;
可选:优化全局中间件逻辑
当前server.js中对所有请求都执行checkMarket和checkUser,可能造成不必要的资源消耗。可以将全局检查改为仅在需要的路由前单独使用中间件,避免冲突。验证修复效果
重启服务器后重新登录Market用户,检查控制台是否还输出“No token jwt2”,同时验证/jwt2id接口是否能正常返回Market用户ID。
内容的提问来源于stack exchange,提问作者Gabriel Bidias
相关产品推荐
相关产品推荐

