使用 sequelize 的 passport js 本地身份验证

passport js local authentication using sequelize

我正在尝试将护照本地身份验证与 sequelize 结合使用。当我提交登录表单时,request/respond 循环永远不会结束,终端中也没有错误消息。

这是我所有的代码:

app.js

var Sequelize = require('sequelize'),
    express = require('express'),
    bodyParser = require('body-parser'),
    cookieParser = require('cookie-parser'),
    passport = require('passport'),
    LocalStrategy = require('passport-local').Strategy,
    User = require('./models/users');
    ........ and other imports.....

    //route import , model  injection
    var auth = require('./routes/auth')(User);

    .......................
app.use(session({
    store: new RedisStore(),
    secret: 'keyboard cat',
    resave: false,
    saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());

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

passport.deserializeUser(function(id, done) {
    User.findById(id).then(function(user){
        done(null, user);
    }).catch(function(e){
        done(e, false);
    });
});

passport.use(new LocalStrategy(
    function(username, password, done) {
       User.findOne({where: {username: username}}).then(function(err, user) {
           if (err) { return done(err); }
           if (!user) {
               console.log('Incorrect username.');
               return done(null, false, { message: 'Incorrect username.' });
           } else if (password != user.password) {
               console.log('Incorrect password');
               return done(null, false, { message: 'Incorrect password.' });
           } else {
               console.log('ok');
               done(null, user);
           }
        });

    }

));

和routes/auth.js :

var express = require('express'),
    passport = require('passport');

var routes = function(User) {
    var router = express.Router();

    // routes for registration
    router.route('/register')
        .get(function(req, res) {
            res.render('register');
        })
        .post(function(req, res) {
           User.count().then(function(number) {
               if (number >= 1) {
                   res.redirect('/auth/login');
               } else {
                   User.create({
                       username: req.body.username,
                       password: req.body.password
                   });

                   res.redirect('/auth/login');
               }
           });
        });
    //routes for login
    router.route('/login')
        .get(function(req, res) {
            res.render('login');
        })
        .post(function(req, res) {
            passport.authenticate('local', { successRedirect: '/dashboard',
                failureRedirect: '/auth/login' });

        });
    return router;
};

module.exports = routes;

为什么 request/response 循环永远不会结束?

您当前对“./login”的中间件定义 POST 不正确并且不会发送响应,这就是它不会结束(直到超时)的原因。

不是在中间件函数中调用passport.authenticate,调用passport.authenticate的结果应该用作中间件本身。我建议如下:

router.route('/login')
    .get(function(req, res) {
        res.render('login');
    })
    .post(passport.authenticate('local', { successRedirect: '/dashboard',
            failureRedirect: '/auth/login' });
    );

请参阅 http://passportjs.org/docs/authenticate 示例。

注册码竞争条件

你没有问过这个问题,但你的中间件中存在“./register”的竞争条件POST。

User.create returns 保存创建用户的承诺。在该承诺得到解决之前,无法保证用户存在于后备数据存储中。但是,在调用创建之后,您的代码立即重定向到登录端点,该端点将查询该用户的数据库。

这里有一些代码可以避免这个问题:

User.create({ ... })
.then(function() {
  res.redirect('/auth/login');
})
.catch(function(err) {
  // Handle rejected promise here 
})

包含 catch 是因为处理被拒绝的承诺和抛出的异常始终是一种好的做法。