模型“用户”的路径“_id”中值“586cc8b3ea780c071bbe2469”的值“586cc8b3ea780c071bbe2469”转换为 ObjectId 失败

Posted

技术标签:

【中文标题】模型“用户”的路径“_id”中值“586cc8b3ea780c071bbe2469”的值“586cc8b3ea780c071bbe2469”转换为 ObjectId 失败【英文标题】:Cast to ObjectId failed for value "586cc8b3ea780c071bbe2469" at path "_id" for model "User" 【发布时间】:2017-05-18 14:39:34 【问题描述】:

我看到了一些与我类似的帖子,但我仍然收到同样的错误

这是我的用户架构

var mongoose = require('mongoose');
var bcrypt   = require('bcrypt-nodejs');

var userSchema = mongoose.Schema(
  local: 
    email: String,
    password: String,
  ,
);

userSchema.methods.generateHash = function(password) 
  return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
;
userSchema.methods.validPassword = function(password) 
  return bcrypt.compareSync(password, this.local.password);
;
module.exports = mongoose.model('User', userSchema);

我的路线

var express = require('express');
var passport = require('passport');
var router = express.Router();

router.get('/', function(req, res, next) 
  res.render('index',  title: 'Express' );
);

router.get('/login', function(req, res, next) 
  res.render('login.ejs',  message: req.flash('loginMessage') );
);

router.get('/signup', function(req, res) 
  res.render('signup.ejs',  message: req.flash('loginMessage') );
);

router.get('/profile', isLoggedIn, function(req, res) 
  res.render('profile.ejs',  user: req.user );
);

router.get('/logout', function(req, res) 
  req.logout();
  res.redirect('/');
);

router.post('/signup', passport.authenticate('local-signup', 
  successRedirect: '/profile',
  failureRedirect: '/signup',
  failureFlash: true,
));

router.post('/login', passport.authenticate('local-login', 
  successRedirect: '/profile',
  failureRedirect: '/login',
  failureFlash: true,
));

module.exports = router;

function isLoggedIn(req, res, next) 
  if (req.isAuthenticated())
      return next();
  res.redirect('/');

我的 app.js

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var mongoose = require('mongoose');
var flash = require('connect-flash');
var session = require('express-session');

var routes = require('./routes/index');
var users = require('./routes/users');


var configDB = require('./config/database.js');
mongoose.connect(configDB.url);

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded( extended: false ));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session( secret: 'shhsecret' ));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());

require('./config/passport')(passport);


app.use('/', routes);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) 
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
);

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') 
  app.use(function(err, req, res, next) 
    res.status(err.status || 500);
    res.render('error', 
      message: err.message,
      error: err
    );
  );


// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) 
  res.status(err.status || 500);
  res.render('error', 
    message: err.message,
    error: 
  );
);


module.exports = app;

这是我的passport.js,我使用的是本地护照

var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/user');

module.exports = function(passport) 
  passport.serializeUser(function(user, done) 
    done(null, user.id);
  );
  passport.deserializeUser(function(id, done) 
    User.findById(id, function(err, user) 
      done(err, user);
    );
  );

  passport.use('local-signup', new LocalStrategy(
    usernameField: 'email',
    passwordField: 'password',
    passReqToCallback: true,
  ,
  function(req, email, password, done) 
    process.nextTick(function() 
      User.findOne( 'local.email':  email , function(err, user) 
        if (err)
            return done(err);
        if (user) 
          return done(null, false, req.flash('signupMessage', 'That email is already in use.'));
         else 
          var newUser = new User();
          newUser.local.email = email;
          newUser.local.password = newUser.generateHash(password);
          newUser.save(function(err) 
            if (err)
              throw err;
            return done(null, newUser);
          );
        
      );
    );
  ));

  passport.use('local-login', new LocalStrategy(
    usernameField: 'email',
    passwordField: 'password',
    passReqToCallback: true,
  ,
  function(req, email, password, done) 
    User.findOne( 'local.email':  email , function(err, user) 
      if (err)
          return done(err);
      if (!user)
          return done(null, false, req.flash('loginMessage', 'No user found.'));
      if (!user.validPassword(password))
          return done(null, false, req.flash('loginMessage', 'Wrong password.'));
      return done(null, user);
    );
  ));
;

passport 可以将用户保存到数据库中

expressauth 5 > db.users.find()
 "_id" : ObjectId("586cc8b3ea780c071bbe2469"), "local" :  "password" : "$2a$08$vANw7GJIk8RUVEpJWnwSpOVQ77RuHCjbXiGoQVl.Fx/thhbMkEVWu", "email" : "david@david.com" , "__v" : 0 
expressauth 6 >

对于模型“用户”的路径“_id”中的值“586cc8b3ea780c071bbe2469”,转换为 ObjectId 失败

我已经构建了几个使用护照 oauth 的应用程序,与上面显示的方式完全相同。所以我不知道为什么会出现这个错误。

有什么建议吗?

【问题讨论】:

【参考方案1】:

mongoose 版本 > 4.7.2 也有同样的问题

问题是关于bson 包。

我通过安装旧版本的猫鼬解决了这个问题。

npm install mongoose@4.7.2

或者您可以更改 package.json 以使用确切的版本 4.7.2 "mongoose": "4.7.2"

问题解决后,您可以更新到较新的版本。您可以在here 上跟踪它。

【讨论】:

【参考方案2】:

passport 中的 serializeUser 函数中存在错误。

您需要使用user._id 而不是user.id

因为在您的UserSchema 中没有field 作为id,所以user.id 将是undefined,而deserializing 是用户,undefined 不是typeOf ObjectId,因此它抛出了错误。

试试这个:

passport.serializeUser(function(user, done) 
    done(null, user._id);
  );

更新:

在您的 deserializeUser 中执行此操作:

将即将到来的id 转换为ObjectId,只是为了确定,然后将ID 转换为query User

var userId = mongoose.Schema.Types.ObjectId(id);
User.findById(userId , function(err, user) 
   done(err, user);
);

不要忘记在同一个文件中包含mongoose

var mongoose=require('mongoose');

希望这会对你有所帮助。

【讨论】:

我更新了 user._id,但我仍然遇到同样的错误。但是在反序列化用户函数中出现了错误。 你能告诉我console.log(id)deserializeUser中打印了什么吗? 在 deserializeUser 中打印出的 id 与我收到错误“586cc8b3ea780c071bbe2469”时显示的 id 相同。 你还在面对这个问题吗? 将猫鼬版本更改为 4.7.2 对我有用,感谢您的帮助。【参考方案3】:

这是由于最新版本的猫鼬,您必须使用findOneAndRemove 而不是FindByIdAndRemove

那是演员objectId的问题。

【讨论】:

以上是关于模型“用户”的路径“_id”中值“586cc8b3ea780c071bbe2469”的值“586cc8b3ea780c071bbe2469”转换为 ObjectId 失败的主要内容,如果未能解决你的问题,请参考以下文章

CastError:模型“用户”的路径“_id”处的值“未定义”转换为 ObjectId 失败

模型“用户”的路径“_id”处的值“ id: '5f1c64aa177bf9379491ecc8'”转换为 ObjectId 失败

Mongoose CastError:模型“Post”的路径“_id”处的值“未定义”转换为 ObjectId 失败

对于模型的路径“_id”处的值,转换为 ObjectId 失败

CastError:模型的路径“_id”处的值“:id”转换为 ObjectId 失败

模型的路径“_id”处的值“”转换为 ObjectId 失败