【问题标题】:why mongoose won't create an ObjectID为什么猫鼬不会创建 ObjectID
【发布时间】:2020-10-23 01:10:31
【问题描述】:

我有一个 JSON Web 令牌,一旦它被验证,它就会给我一个字符串,它是我想要查找的用户的对象 ID 值,但似乎每次我尝试查询时都会将它解析为猫鼬对象 ID永远找不到我的用户,我是否正确解析它?我总是得到一个 401 无效的 token paylaod

logRoute.get('/user', (req, res) => {
  let token = req.body;
  User.findOne({_id: mongoose.Types.ObjectId(jwt.verify(token.token, 'secretkey').subject)}, (error, user) => {
    if (error) {
      console.log(error)
    } else {
      if (!user) {
        res.status(401).send('invalid token payload')
      } else {
        let userData = {firstname: user.firstname, lastname: user.lastname, type: user.type}
        res.status(200).send(userData)
      }
    }
  })
})

我的用户数据

{
    "_id": {
        "$oid": "5efc7d60ba7a8d3db08ca767"
    },
    "type": "teacher",
    "firstname": "arandomfirstname",
    "lastname": "arandomlastname",
    "login": "random1",
    "pwd": "arandompassword"
}

console.log(jwt.verify(req.body.token, 'P3GPROJECT'))

还给我

{ subject: '5efc7d60ba7a8d3db08ca767', iat: 1593690718 }

编辑:

用户模型

const mongoose = require('mongoose');

const Schema = mongoose.Schema;

const userSchema = new Schema({
  _id: String,
  pwd: String,
  lastname: String,
  firstname: String,
  type: String
});

module.exports = mongoose.model('user', userSchema, 'user');

【问题讨论】:

  • 我不认为mongoose有问题,我认为你的令牌中没有id。 Mongoose 理解 id 即使它是一个字符串,因此请确保 console.log(jwt.verify(req.body.token, 'P3GPROJECT')) 返回正确的对象。
  • 我在控制台记录了它并且 jwt 验证返回给我正确的 id
  • 请把它放在你的问题上
  • 我已经回答了您的问题并以更好的方式重写了您的代码。
  • 请将架构放入您的用户模型

标签: javascript mongoose mongodb-query jwt


【解决方案1】:

您必须从模型架构中删除 _id: String,因为您已将 ObjectId 作为值(不是字符串),并且它使猫鼬将您的输入转换为字符串,而不是 ObjectId

所以:

const userSchema = new Schema({
  _id: String,
  pwd: String,
  lastname: String,
  firstname: String,
  type: String
});

变成:

const userSchema = new Schema({
  pwd: String,
  lastname: String,
  firstname: String,
  type: String
});

或者您可以将其保留为字符串,但必须定义生成正确_id的逻辑:

const uuid = require('short-uuid');
const userSchema = new Schema({
  _id: {
    type: Schema.Types.String,
    default: uuid.generate(),  // this will generate unique string
  },
  pwd: String,
  lastname: String,
  firstname: String,
  type: String
});

附:请记住,如果您想使用_id: String,您必须删除旧文档或手动将它们转换为{_id: "id here"} 而不是{_id: ObjectId("id here")}

奖金:

我还建议您创建中间件并从用户授权检查中分离令牌处理。 它将允许您在每个请求中不重复访问令牌检查,并将帮助您了解您在哪一步做错了。

然后做你想做的事。

  1. jwt.verify 如果无效则抛出错误,这就是为什么我把 try catch 放在一边。

  2. 我将subject 提取为userId,如果它不存在也意味着令牌无效,否则我将处理传递给路由中的next 处理程序。

  3. authorizeUser 从之前的中间件获取req.accessToken.userId 并尝试检查用户是否存在。如果是 - 那么它将完整的用户对象存储在 req.user 中,否则也会以 401 结尾。

  4. 最后,路由处理进入执行逻辑的最后一步,也可以为空 res.status(200).send(req.user)

const checkAccessToken = (req, res, next) => {
  try {
    const {subject: userId} = jwt.verify(req.body.token, 'secretkey');
    if (!userId) throw new Error('Token data does not contain user id');
    req.accessToken = {userId};
    next();
  }
  catch (error) {
    console.error(error);
    res.status(401).send({message: 'Invalid access token'});
  }
};

const authorizeUser = async (req, res, next) => {
  try {
    const user = 
      await User.findById(req.accessToken.userId)
                .select('_id firstname lastname type')
                .lean();
    if (!user) {
      return res.status(401).send({message: 'Unauthorized'});
    }
    req.user = user;
    req.user.id = req.accessToken.userId;
    next();
  }
  catch (error) {
    console.error(error);
    res.status(500).end();
  }
};

logRoute.get(
  '/user', 
  checkAccessToken, // checking token and putting user id to `req.user.id`
  authorizeUser,    // checking if user exists in database and putting it as `req.user` object
  async (req, res) => {  // handling some logic or simply returning `req.user` object
    // some extra logic here...
    res.status(200).send(req.user);
  }
);

【讨论】:

  • 感谢您的回答,但您的代码返回给我一个 {subject: id} = session; ^ SyntaxError: Unexpected token '='
  • 我的控制台给我一个 TypeError [ERR_INVALID_ARG_TYPE]:“块”参数必须是字符串类型或 Buffer 实例。在 processTicksAndRejections(内部/process/task_queues.js:97:5) { 代码:'ERR_INVALID_ARG_TYPE' }
猜你喜欢
  • 2019-08-10
  • 2017-04-06
  • 2013-03-24
  • 2020-07-25
  • 2017-10-24
  • 2016-11-21
  • 2016-01-01
  • 2016-11-06
  • 1970-01-01
相关资源
最近更新 更多