PassportJs 身份验证无限循环和执行(默认)查询

Posted

技术标签:

【中文标题】PassportJs 身份验证无限循环和执行(默认)查询【英文标题】:PassportJs Authentication Infinite Loop and Execute(default) query 【发布时间】:2017-08-04 13:38:54 【问题描述】:

我正在尝试使用 PassportJs 和 Sequelize 构建身份验证系统。我使用 Sequelize 自己制作了注册系统。我只想将 PassportJS 用于登录。

它不会将我重定向到 failureRedirect 路由,也不会重定向到 SuccessRedirect 路由,但是当提交表单时它会进入无限循环并在我的控制台中出现以下消息:

 Executing (default): SELECT `id`, `username`, `lastName`, `password`,  `email`, `phone`, `createdAt`, `updatedAt` FROM `user` AS `user` LIMIT 1;   

我的项目结构如下: users_model.js 、 index.js 和 users.js(控制器)。

我的 index.js 中的代码如下所示:

//===============Modules=============================
var express = require('express');
var bodyParser = require('body-parser');   
var session = require('express-session');
var authentication= require('sequelize-authentication');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var passportlocal= require('passport-local');
var passportsession= require('passport-session');

var User = require('./models/users_model.js');


passport.use(new LocalStrategy(
  function(username, password, done) 
    User.findOne( username: username , function(err, user) 
      if (err)  return done(err); 
      if (!user) 
        return done(null, false,  message: 'Incorrect username.' );
      
      if (!user.validPassword(password)) 
        return done(null, false,  message: 'Incorrect password.' );
      
      return done(null, user);
    );
  
));


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

passport.deserializeUser(function(id, done) 
  User.findById(id, function(err, user) 
    done(err, user);
    console.log(id);
  );
);


var users= require('./controllers/users.js');    
var app = express();


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


app.use(bodyParser.urlencoded( extended: true ));
app.use(bodyParser.json());

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

//-------------------------------------------Setup Session------------
app.use(session(
    secret: "ceva",
    resave:true,
    saveUninitialized:true,
    cookie:,
    duration: 45 * 60 * 1000,
    activeDuration: 15 * 60 * 1000,
));


// Passport init
app.use(passport.initialize());
app.use(passport.session());

//------------------------------------------------Routes----------
app.get('/', function (req, res) 
     res.send('Welcome!');
);

   //-------------------------------------Server-------------------

app.listen(3000, function () 
  console.log('Example app listening on port 3000!');
);

在我的控制器中,我使用 Sequelize 自己制作了注册系统。在 users.js 中,我有:

var express = require('express');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var passportlocal= require('passport-local');
var passportsession= require('passport-session');
var router = express.Router();

var User = require('../models/users_model.js');

//____________________Initialize Sequelize____________________

const Sequelize = require("sequelize");
const sequelize = new Sequelize('millesime_admin', 'root', '', 
  host: 'localhost',
  dialect: 'mysql',
  pool: 
    max: 5,
    min: 0,
    idle: 10000
  
); 

//________________________________________


router.get('/',function(req,res)
res.send('USERS');
);

router.get('/register', function(req, res) 
     res.render('registration', title: "Register" );
);

router.post('/register', function(req, res) 
    var email = req.body.email;
    var password = req.body.password;
    var username= req.body.username;
    var lastname= req.body.lastname;
    var phone= req.body.phone;

   User.findAll().then(user => 
    usersNumber = user.length;
    x=usersNumber+1;
    var y =usersNumber.toString();
    var uid='ORD'+ y;

    User.sync().then(function ()
      return User.create(
      id:uid,
      email: email,
      password:password,
      username: username,
      lastName: lastname,
      phone: phone,
         );
    ).then(c => 
        console.log("User Created", c.toJSON());
         res.redirect('/users');
    ).catch(e => console.error(e));    
 );    
);

router.get('/login',function(req,res)
    res.render('authentication');
);

//router.post('/login', function(req, res, next) 
//    console.log(req.url);  // '/login'
//    console.log(req.body);
// I got these: username: 'username', password: 'parola'  
//    passport.authenticate('local', function(err, user, info) 
//        console.log("authenticate");
//        console.log('error:',err);
//        console.log('user:',user);
//        console.log('info:',info);
//    )(req, res, next);
//);


router.post('/login', passport.authenticate('local',  
    successRedirect: '/events',                    
    failureRedirect: '/users/register' 
    ));

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

//__________________________________________
module.exports = router;

【问题讨论】:

【参考方案1】:

主要问题:不是无限循环,而是Sequelize的错误使用

这不是一个无限循环,而只是来自服务器的挂起响应,该响应将以超时错误结束。

当你这样做时:

passport.use(new LocalStrategy(
  function(username, password, done) 
    ...
  
));

...passportexpress 等待调用 done 函数。一旦它是done(),它们就会在中间件链中前进并将响应发送给客户端。

done 函数没有被调用,因为 Sequelize 似乎不支持回调函数,但承诺。所以,调用 Sequelize 方法的正确方法是:

User.findOne( username: username ).then(user => 
  if (!user) 
    return done(null, false,  message: 'Incorrect username.' );
  
  if (!user.validPassword(password)) 
    return done(null, false,  message: 'Incorrect password.' );
  
  done(null, user);
).catch(err => done(err));

(de)序列化会话用户

用户实例中似乎没有id字段,而是userid。因此我们必须这样做:

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

passport.deserializeUser(function(id, done) 
  User.findOne( userid: id ).then(user => 
    done(null, user);
    console.log(id);
  ).catch(err => done(err));
);

作为参考,this commit 修复了这些问题。

【讨论】:

是的,现在可以了!感谢您的帮助,您的回答和解释。我现在明白了!谢谢! :)

以上是关于PassportJs 身份验证无限循环和执行(默认)查询的主要内容,如果未能解决你的问题,请参考以下文章

如果用户通过一次身份验证,防止用户再次登录passportjs?

Express Passportjs在路由器回调中未进行身份验证

javascript PassportJS身份验证设置#passportjs #cookiesession #nodejs

PHPMyAdmin 单点登录身份验证无限重定向循环

通过回调或猫鼬模型验证 PassportJS?

Nodejs和PassportJs:如果身份验证失败,则不会调用passport.authenticate后重定向中间件