使用 Passport.js、express-session 和 express-mysql-session 进行用户身份验证
Posted
技术标签:
【中文标题】使用 Passport.js、express-session 和 express-mysql-session 进行用户身份验证【英文标题】:User authentication using Passport.js, express-session and express-mysql-session 【发布时间】:2018-10-21 20:13:17 【问题描述】:我正在尝试使用 Node.js、Express、Passport.js 和 mysql 数据库创建用户身份验证。我能够注册用户(从代码中排除,以便于阅读)并且我能够登录(我从护照获得 succesRedirect) - 但我无法序列化用户并且我很确定我的会话有问题。
当我运行我的代码时,我收到以下错误:
错误:无法将用户序列化到会话中
这是我的代码:
var express = require('express'),
app = express(),
bodyParser = require('body-parser'),
mysql = require('mysql'),
generator = require('generate-password'),
cookieParser = require('cookie-parser'),
expressValidator = require('express-validator'),
session = require('express-session'),
passport = require('passport'),
MySQLStore = require('express-mysql-session')(session),
LocalStrategy = require('passport-local').Strategy,
bcrypt = require('bcrypt');
const saltRounds = 10;
app.set("view engine", "ejs");
app.use(express.static(__dirname + "/public"));
app.use(bodyParser.urlencoded(extended: true));
app.use(expressValidator());
app.use(cookieParser());
var options =
host : 'localhost',
user : 'MY-USER',
database : "c9",
password : "",
multipleStatements: true
;
var sessionStore = new MySQLStore(options);
app.use(session(
secret: 'dfsfjdssdvsdvawdslepsv',
resave: true,
store: sessionStore,
saveUninitialized: true
));
app.use(passport.initialize());
app.use(passport.session());
//Start MYSQL database
var connection = mysql.createConnection(
host : 'localhost',
user : 'MY-USER',
database : "c9",
password : "",
multipleStatements: true
);
connection.connect(function(err)
if(!err)
console.log("Database is connected ...");
else
console.log("Error connecting database ...");
);
app.get("/", isAuthenticated, function(req, res, next)
res.render('dashboard');
);
//show login form
app.get("/login", function(req, res)
res.render("login");
);
//login
app.post("/login", passport.authenticate(
'local',
successRedirect: '/',
failureRedirect: '/login'
));
//create new user
app.post("/users", function(req, res)
var today = new Date();
//generate password + salt
var password = generator.generate(
length: 8,
numbers: true,
symbols: false
);
var salt = bcrypt.genSaltSync(saltRounds);
var hash = bcrypt.hashSync(password, salt);
console.log(salt);
//create user object
var user =
first_name : req.body.first_name,
last_name : req.body.last_name,
email : req.body.email,
password : hash,
salt : salt,
created : today,
modified : today,
user_role : req.body.user_role
;
//check if email already exists in database
connection.query('SELECT email FROM users WHERE email=?', user.email, function(error, results, fields)
if(error)
throw error;
if(results.length > 0)
//email already exists in database
res.redirect("/");
return;
else
//email does not exist from before
//add user to database
connection.query('INSERT INTO users SET ?', user, function(err, result)
if(err) throw err;
connection.query('SELECT LAST_INSERT_ID() as user_id', function(error, results, fields)
if(error) throw error;
);
//Send registration email
res.redirect("users");
);
);
);
passport.serializeUser(function(user, done)
done(null, user.id);
);
passport.deserializeUser(function(id, done)
connection.query('SELECT * FROM users WHERE id = ?', id, function (err, rows)
done(err, rows[0]);
);
);
//Authenticate users
passport.use(new LocalStrategy(
function(username, password, done)
connection.query('SELECT password, salt FROM users WHERE email = ?', [username], function(err, results, fields)
//DB error
if(err) done(err);
//no user was found
if(results.length === 0)
done(null, false);
var salt = results[0].salt;
if(bcrypt.hashSync(password, salt) === results[0].password)
//Success
return done(null, true);
else
//Wrong password
return done(null, false);
);
));
function isAuthenticated(req, res, next)
if (req.isAuthenticated())
return next();
res.redirect('/login');
app.listen(process.env.PORT, process.env.IP, function()
console.log("Server started...");
);
在我看来,我正在做的正是我从不同的教程和文档中读到的东西。谁能看到我失败的地方?
用户数据库如下所示:
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`last_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`salt` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
`user_role` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
会话数据库如下所示:
CREATE TABLE IF NOT EXISTS `sessions` (
`session_id` varchar(128) COLLATE utf8mb4_bin NOT NULL,
`expires` int(11) unsigned NOT NULL,
`data` text COLLATE utf8mb4_bin,
PRIMARY KEY (`session_id`)
) ENGINE=InnoDB
【问题讨论】:
【参考方案1】:发现问题。
passport.serializeUser(function(user, done)
done(null, user.id);
);
应该获取并发送一个用户 ID。在我的代码中,它需要一个用户。
现在解决了!
【讨论】:
以上是关于使用 Passport.js、express-session 和 express-mysql-session 进行用户身份验证的主要内容,如果未能解决你的问题,请参考以下文章
为啥除了 passport.js 还要使用 cookie-session?
如何在 passport-facebook / Passport.js 中捕获 FacebookAuthorizationError?