Node JS + Passport login



我正在尝试将我的第一个node-js应用程序配置为使用passport登录。

所以首先要做的事。我创建了一个/app/config/express.js文件来配置express。所以我的app.js更简单:

var app = require('./app/config/express')();
app.listen(3001, function(){
console.log("Servidor rodando");
});

好的。。。太酷了。但是!我的express.js文件太大了。也许你可以给我一些关于如何重构的提示?

我添加了一些评论和一些问题,我很想让这个代码变得更好。

var express = require('express');
var load = require('express-load');
var expressValidator = require('express-validator');
var bodyParser = require('body-parser');
var passport = require('passport');
var Strategy = require('passport-local').Strategy;
var session = require('express-session');
var flash = require("connect-flash");
module.exports = function() {
// PLEASE READ 1
//
// 
// Functions to organize code better.
// PS: if this functions are outside "module.exports", then Express
// doesnt 'inject' the 'app.infra' variable .... 
// Is there a workaround to move these functions outta here?
//
// 
function configureAuth(){
passport.use(new Strategy({
passReqToCallback : true
},
function(req, username, password, cb) {
var connection = app.infra.connectionFactory();
var userDao = new app.infra.dao.UserDao(connection);
userDao.login(username, password, function(err, user){
if (err) {
return cb(err);
}
if (!user) {
return cb(null, false);
}

return cb(null, user);
});
connection.end();
}));
//
// 
// HERE IT IS!
//
//
passport.serializeUser(function(user, cb) {
cb(null, user.id);
});
passport.deserializeUser(function(id, cb) {
cb(null, user);
});
}
function configureExpressLibs(app){
app.set('view engine', 'ejs');
app.set('views','./app/views');
app.use('/static', express.static('./app/public'));
app.use(flash());
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(expressValidator());
app.use(session({
secret: '086this 54is 23unkowned 67',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
}
function configureErrors(app){
app.use(function(err, req, res, next) {
console.error(err.stack)
next(err)
});
app.use(function(req,res,next){
res.status(404).render('errors/404');
next();
});

app.use(function(error, req,res,next){
res.status(500).render('errors/500');
next();
});
}
// PLEASE READ 2
// 
// 
//  I've moved this to 'LoginController.js' in my routes folder but
//  I didnt work... So I moved it here. Is there a work around?
//
//
function configureLoginRoutes(app){
function redirectToIndexIfLoggedIn(req, res, next) {
if (req.isAuthenticated())
res.redirect('/');
return next();
}
app.get('/login', redirectToIndexIfLoggedIn, function(req, res){
res.render('login/login');
});
app.post('/login', passport.authenticate('local', {
successRedirect : '/',
failureRedirect : '/login',
failureFlash : 'Invalid username or password.'
}));
app.get('/logout', function(req, res){
req.logout();
req.session.destroy();
res.redirect('/');
});
}

var app = express();
configureExpressLibs(app);
configureAuth();
configureLoginRoutes(app);

load('routes',{cwd: 'app'})
.then('infra')
.into(app);
configureErrors(app);
return app;
}

所以现在的问题是,当我登录时(不管用户是对是错),我会得到一个:

Error: Failed to serialize user into session

我在谷歌上搜索了一下,发现这是因为人们忘记了实现"serializeUser"。但我做到了。请在上面的代码上用"HERE IT IS"来检查评论。

谢谢大家。抱歉代码太大了。但我正在学习,我希望在你的帮助下让事情变得更好。

EDIT我的反序列化方法错误。我用修复了它

passport.deserializeUser(function(id, cb) {
var connection = app.infra.connectionFactory();
var userDao = new app.infra.dao.UserDao(connection);
userDao.findById(id, function(err, user) {
done(err, user);
});
connection.end();
});

但是应用程序仍然失败。同样的错误。

编辑解决方案

结果发现我的实现是错误的。您知道,mysql总是返回一个数组。因此,我纠正了我的代码如下:

function(req, username, password, cb) {
var connection = app.infra.connectionFactory();
var userDao = new app.infra.dao.UserDao(connection);
userDao.login(username, password, function(err, user){
if (err) {
return cb(err);
}
if (!user) {
return cb(null, false);
}
// HERE
return cb(null, user[0]);
});
connection.end();
}));

这里:

passport.deserializeUser(function(id, cb) {
var connection = app.infra.connectionFactory();
var userDao = new app.infra.dao.UserDao(connection);
userDao.findById(id, function(err, user) {
// HERE
cb(err, user[0]);
});
connection.end();
});
} 

当你调用cb(null,user)时,我认为你的this.user没有在deserializeUser中设置,所以在app.use(passport.session())之后创建你自己的中间件,把它放在this.user中,如下所示:

app.use(function * setUserInContext (next) {
this.user = this.req.user
yield next
})

干杯:)

最新更新