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

Node Express Passport JWT会话存储及密码修改路由问题排查

问题修复方案

1. 修复Passport-JWT核心配置错误

req.user._id不正确的根源是Passport-JWT的查询逻辑错误,以及Passport未初始化:

修正index.js代码

  • 启用Passport初始化:取消注释app.use(passport.initialize());,即使使用无Session的JWT,仍需初始化Passport。
  • 修正用户查询条件:MongoDB默认主键为_id而非id,且需匹配JWT payload中的sub字段(应为用户_id):
// index.js 中Passport-JWT验证回调
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
    console.log(jwt_payload)
    // 将查询条件从id改为_id,匹配jwt_payload.sub
    User.findOne({_id: jwt_payload.sub}, function(err, user) {
        if (err) {
            return done(err, false);
        }
        if (user) {
            return done(null, user);
        } else {
            return done(null, false);
        }
    });
}));
  • 删除无用的Session序列化代码:serializeUser和deserializeUser是Session认证专用逻辑,JWT无Session模式下直接删除:
// 移除以下代码块
passport.serializeUser((user, done) => {
    done(null, user.id);
});
  
passport.deserializeUser((id, done) => {
    // Find and return the user by ID, if needed
    // ...
});

2. JWT Token的存储与使用

登录成功后,前端需将返回的Token存储(推荐用HttpOnly Cookie,或临时存在localStorage),后续请求时:

  • 在请求头Authorization中添加Bearer <你的Token>
  • Postman测试时,在Headers面板添加键Authorization,值为Bearer xxxxxx(替换为登录接口返回的Token)

3. 完善修改密码路由逻辑

当前路由仅获取ID,需补充密码验证与更新逻辑,同时限制用户只能修改自身密码:

// auth.js 中的修改密码路由
router.patch(
    '/profile/:userId/change-password',
    passport.authenticate('jwt', { session: false }),
    async (req, res) => {
        try {
            const userId = req.params.userId;
            const authenticatedUserId = req.user._id.toString(); // 转为字符串与参数ID匹配

            // 验证用户只能修改自己的密码
            if (userId !== authenticatedUserId) {
                return res.status(403).json({error: '无权修改他人密码'});
            }

            const {oldPassword, newPassword} = req.body;
            const user = await User.findById(userId);

            // 验证旧密码正确性
            const isOldPwValid = await bcrypt.compare(oldPassword, user.password);
            if (!isOldPwValid) {
                return res.status(401).json({error: '旧密码不正确'});
            }

            // 哈希新密码并保存
            const hashedNewPw = await bcrypt.hash(newPassword, 10);
            user.password = hashedNewPw;
            await user.save();

            return res.status(200).json({message: '密码修改成功'});
        } catch (err) {
            return res.status(500).json({error: '服务器错误', details: err.message});
        }
    }
);

4. 验证getToken函数正确性

确保utils/helpers.js中的getToken生成的JWT payload包含正确的sub字段(用户_id):

// utils/helpers.js
const jwt = require('jsonwebtoken');
exports.getToken = (user) => {
    return jwt.sign(
        {sub: user._id.toString()}, // 确保sub为用户_id的字符串形式
        process.env.JWT_SECRET,
        {expiresIn: '7d'} // 设置合理的过期时间
    );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 08:47:05