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

登录后PassportJS的req.user为undefined问题求助

问题分析与解决方案

你遇到的req.user为undefined的核心原因是混淆了Passport的Session认证与JWT认证机制,同时存在异步逻辑处理不规范、路由未配置JWT验证中间件等问题,以下是具体修复步骤:


1. 移除Session相关配置(JWT模式不需要)

你配置的serializeUser和deserializeUser是Passport用于Session持久化用户的方法,但JWT是无状态认证,不需要依赖Session存储用户信息。直接删除以下代码:

passport.serializeUser((user, done) => {
    console.log("Serializing...");
    return done(null, user.id);
});

passport.deserializeUser(async (id, done) => {
    console.log("Deserializing...");
    console.log({ id });
    return done(null, await searchUser({ id }));
});

2. 修复JWT策略的错误处理逻辑

Passport的策略回调遵循cb(错误对象, 用户对象, 信息对象)的规范,原代码中找不到用户时返回cb(true)不符合规范,会导致验证逻辑异常,修改如下:

passport.use(
    new JWTStrategy(
        {
            jwtFromRequest: function (req) {
                let token = null;
                if (req && req.cookies) {
                    token = req.cookies["token"];
                }
                return token;
            },
            secretOrKey: process.env.TOKEN_SECRET,
        },
        async function (jwtPayload, cb) {
            try {
                const user = await searchUser({
                    $or: [{ email: jwtPayload.email }, { username: jwtPayload.username }],
                });

                if (!user) {
                    // 验证失败,返回null+false
                    return cb(null, false);
                }
                return cb(null, user);
            } catch (err) {
                // 抛出错误对象
                return cb(err);
            }
        }
    )
);

3. 修正登录路由的异步逻辑与冗余代码

req.logIn是Session认证专用方法,JWT模式下完全不需要调用。同时要确保响应在逻辑完成后发送,修改后的登录路由:

router.post("/login", (req, res, next) => {
    passport.authenticate("login", function (err, user, info) {
        if (err) return res.status(500).json(ERRORS.UNKNOWN_ERROR);
        if (!user) return res.status(401).json(info);

        const token = jwt.sign(
            _.pick(user, [
                "name",
                "surname",
                "email",
                "username",
                "accountType",
                "canComment",
                "id",
            ]),
            process.env.TOKEN_SECRET
        );

        // 增加安全配置,防止前端JS窃取cookie
        res.cookie("token", token, { 
            expires: new Date(2147483647 * 1000),
            httpOnly: true,
            secure: process.env.NODE_ENV === 'production'
        });

        res.status(200).json({
            ...MESSAGES.LOGIN_SUCCESS,
            user: _.pick(user, ["name", "surname", "email", "username", "accountType", "canComment"])
        });
    })(req, res, next);
});

4. 为受保护路由添加JWT验证中间件

登录后,所有需要获取req.user的路由必须通过passport.authenticate('jwt')中间件验证token,示例:

// 获取当前用户信息的示例路由
router.get("/profile", passport.authenticate('jwt', { session: false }), (req, res) => {
    // 此时req.user即为验证通过的用户对象
    res.status(200).json(req.user);
});

注意必须添加{ session: false },明确告诉Passport不要使用Session机制。


5. 确保已配置Cookie解析中间件

如果你的Express应用还没配置cookie-parser,需要先安装并启用,否则req.cookies会为undefined,JWT策略无法读取token:

npm install cookie-parser
const cookieParser = require('cookie-parser');
app.use(cookieParser());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:47:21