用户登录/注册后修改密码时无法从MongoDB获取userId问题
系统设定用户登录后持有有效Token即可修改密码,路由配置如下:
import UserController from "../controllers/userController.js"; import checkUserAuth from "../middlewares/auth-middleware.js"; // route level middleware router.use("/changepassword", checkUserAuth); router.post("/changepassword", UserController.changePassword);
身份验证中间件逻辑:
let token; const { authorization } = req.headers; if (authorization && authorization.startsWith("Bearer")) { try { token = authorization.split(" ")[1]; // verify user token console.log(authorization); console.log(token); const { userId } = Jwt.verify(token, "5DFE4FG0125DRHcgng"); // get user from token req.user = await UserModel.findById("62fc541298faae7fa6db9035").select( "-password" ); console.log(req.user); next(); } catch (error) { res.send({ status: "failed", message: "unauthorized user" }); } }
调试情况:控制台能正常输出Token值,但用JWT解析出的userId调用UserModel.findById()无法获取用户信息;改用固定ID"62fc541298faae7fa6db9035"则能成功获取用户数据。
Mongoose Schema定义:
import mongoose from "mongoose"; // Define Schema const userSchema = new mongoose.Schema({ name: { type: "String", required: true, trim: true }, email: { type: "String", required: true, trim: true }, password: { type: "String", required: true, trim: true }, tc: { type: "String", required: true }, }); // Model const UserModel = mongoose.model("user", userSchema); export default UserModel;
代码未实际使用解析出的userId:当前中间件里写死了固定ID,根本没用到从JWT解析出的
userId。这是最直接的问题,把查询代码改成req.user = await UserModel.findById(userId).select("-password");再测试。JWT签发时未正确存入用户ID:检查Token生成代码,确认签发时是否将MongoDB用户的
_id赋值给了userId字段。如果签发时字段名错误(比如用id而非userId),或者存入的不是用户真实的_id,会导致解析出的userId无效。数据类型不匹配:MongoDB的
_id是ObjectId类型,JWT解析出的userId是字符串。若字符串格式不符合ObjectId规则(长度不对、含非法字符),Mongoose无法转换成功。可以用mongoose.Types.ObjectId.isValid(userId)验证格式,同时打印userId值对比数据库中的_id。Token签名密钥不一致:虽然能解析出
userId,但如果签发Token的密钥和验证时的"5DFE4FG0125DRHcgng"不一致,解析出的userId可能是篡改或错误的数据。务必确保签发与验证用同一密钥。用户数据已删除:解析出的
userId对应的用户可能已从数据库删除,导致查询无结果。可以直接用该userId在MongoDB客户端手动查询,确认数据是否存在。
内容的提问来源于stack exchange,提问作者Kumar sunil

