在Express 4中设置Passport时遇到404未找到错误

4

我在我的Node.js应用程序中使用passport遇到了很多麻烦。我尝试重新排列app.js中的需求,但仍然无法使其正常工作。下面是出现的错误:

Not Found

404

Error: Not Found
    at /home/salma/Desktop/my-project/app.js:56:13
    at Layer.handle [as handle_request] (/home/salma/Desktop/my-project/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/home/salma/Desktop/my-project/node_modules/express/lib/router/index.js:312:13)
    at /home/salma/Desktop/my-project/node_modules/express/lib/router/index.js:280:7
    at Function.process_params (/home/salma/Desktop/my-project/node_modules/express/lib/router/index.js:330:12)
    at next (/home/salma/Desktop/my-project/node_modules/express/lib/router/index.js:271:10)
    at /home/salma/Desktop/my-project/node_modules/express/lib/router/index.js:618:15
    at next (/home/salma/Desktop/my-project/node_modules/express/lib/router/index.js:256:14)
    at next (/home/salma/Desktop/my-project/node_modules/express/lib/router/route.js:121:14)
    at complete (/home/salma/Desktop/my-project/node_modules/passport/lib/middleware/authenticate.js:250:13)
    at /home/salma/Desktop/my-project/node_modules/passport/lib/middleware/authenticate.js:257:15
    at pass (/home/salma/Desktop/my-project/node_modules/passport/lib/authenticator.js:421:14)
    at Authenticator.transformAuthInfo (/home/salma/Desktop/my-project/node_modules/passport/lib/authenticator.js:443:5)
    at /home/salma/Desktop/my-project/node_modules/passport/lib/middleware/authenticate.js:254:22
    at /home/salma/Desktop/my-project/node_modules/passport/lib/http/request.js:60:7
    at pass (/home/salma/Desktop/my-project/node_modules/passport/lib/authenticator.js:267:43)
    at serialized (/home/salma/Desktop/my-project/node_modules/passport/lib/authenticator.js:276:7)
    at /home/salma/Desktop/my-project/config/passport.js:9:9
    at pass (/home/salma/Desktop/my-project/node_modules/passport/lib/authenticator.js:284:9)
    at Authenticator.serializeUser (/home/salma/Desktop/my-project/node_modules/passport/lib/authenticator.js:289:5)
    at IncomingMessage.req.login.req.logIn (/home/salma/Desktop/my-project/node_modules/passport/lib/http/request.js:50:29)
    at Strategy.strategy.success (/home/salma/Desktop/my-project/node_modules/passport/lib/middleware/authenticate.js:235:13)

这里是我的代码:
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 mongoose = require('mongoose');
var flash    = require('connect-flash');
var passport = require('passport');
var session  = require('express-session');
var routes   = require('./routes/index');
var userRoutes   = require('./routes/user');
var adminRoutes   = require('./routes/admin');
var config = require('./config/index.js');
var MongoStore = require('connect-mongo')(session);

var app = express();

mongoose.Promise = global.Promise;
var db = mongoose.connect(config.dbUrl, config.dbOpts);

// 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(express.static(path.join(__dirname, 'public')));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

var store = new MongoStore({
  mongooseConnection: db.connection
});

app.use(session({
  secret: config.sessionSecret,
  store: store,
  resave: true,
  saveUninitialized: true
}));

app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
require('./config/passport')(passport);

app.use('/', routes);
app.use('/', userRoutes);
app.use('/admin', adminRoutes);

// 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 handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

mongoose.connection.on('open', function(){
  mongoose.connection.db.listCollections(function(error, names) {
    if (error) {
      throw new Error(error);
    } else {
      names.map(function(name) {
        console.log('found collection %s', name);
      });
    }
  });
});

mongoose.connection.on('error', function(error){
  throw new Error(error);
});

module.exports = app;

这是我的登录路由:
路由文件:user.js
var express = require('express');
var User = require('../controllers/user');
var passport = require('passport');
var router = express.Router();

router.get('/', function(req, res, next) {
    res.send('respond with a resource');
});

router.post('/login', passport.authenticate('local',
  { successFlash: 'Success!',
    failureFlash : 'Login failed' }));

这是我处理 passport 认证策略的文件:

config/passport.js:

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

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', new LocalStrategy({
        usernameField : 'email',
        passwordField : 'password',
        passReqToCallback : true
    },
    function(req, email, password, done) {
        User.findOne({ email :  email }, function(err, user) {
            if (err) return done(err);
            if (!user)
                return done(null, false, req.flash('loginMessage', 'This email does not exist.'));
            if (!user.validPassword)
                return done(null, false, req.flash('loginMessage', 'Oops! The password entered is incorrect.'));
            return done(null, user);
        });
    }));
    passport.use(new FacebookStrategy({
        clientID: configAuth.facebookAuth.clientID,
        clientSecret: configAuth.facebookAuth.clientSecret,
        callbackURL: configAuth.facebookAuth.callbackURL,
        profileFields: ["emails", "displayName", "name"]
    }
}

我已经尝试了同一路由文件中的其他路由,以确保这些路由被app.js看到,并且它们都正常工作。只有这个路由没有起作用。请问有人能告诉我哪里出了问题吗?


你能展示一下你的“用户”模型吗? - Ravi Shankar Bharti
@ravishankar 谢谢您的回复。我已经意识到问题并将立即发布答案 :) - SalmaFG
我在回答中提到的问题,是否有效?你是否真的将serializeUser中的代码更改为user._id - Ravi Shankar Bharti
@ravishankar 试过了,也成功了。谢谢! - SalmaFG
2个回答

5
问题出在路由选项successFlashfailureFlash上。 passport.authenticate()函数期望不同的选项,必须按照完全相同的方式使用,否则它们将无法正常工作。因此,当我替换选项以完全匹配文档时:
app.post('/login',
  passport.authenticate('local', { successRedirect: '/',
                                   failureRedirect: '/login',
                                   failureFlash: true })
);

或者

 passport.authenticate('local', function(err, user, info) {
            if (err) return res.status(500).send();
            if (!user) return res.status(400).json({error:info.message});
            req.logIn(user, function(err) {
                if (err) return next(err);
                return res.status(200).json(info.message);
            });
        })(req, res, next);

它起作用了。还有其他调用该函数的方法,在此处列出文档: http://passportjs.org/docs/authenticate


5
解决了我的问题。如果您不想重定向,就必须为 app.post('/login', ...) 提供一个回调函数,否则它会在成功登录时响应404。 - DisplayName

2

根据您收到的错误信息,我猜测您在序列化反序列化用户时遇到了问题。

您所犯的错误非常简单。

序列化用户时,您使用了user.id,而这个值是undefined(我猜测)。因此,在反序列化时,该函数无法获取ID,并且在user集合中查找时出现问题。

应该使用user._id而不是user.id。更改后,您就可以继续了。

替换为:

passport.serializeUser(function (user, done) {
    done(null, user.id);
});

使用:

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

希望这有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接