使用Passport进行身份validation后创build新会话

我已经创build了一个简单的身份validation应用程序与护照(见下面的代码)。 通过会话中间件进行expression,为请求客户端没有会话的每个请求创build一个会话。 我想只在login后分配会话或login后创build一个新的会话。

这是因为我最终将通过HTTPS进行login,并希望阻止黑客劫持已通过身份validation的用户的会话。

这是我的服务器代码:

// Server.js configures the application and sets up the webserver //importing our modules var express = require('express'); var app = express(); var port = process.env.PORT || 8080; var mongoose = require('mongoose'); var passport = require('passport'); var flash = require('connect-flash'); var MongoStore = require('connect-mongo')(express); var configDB = require('./config/database.js'); //Configuration of Databse and App mongoose.connect(configDB.url); //connect to our database require('./config/passport')(passport); //pass passport for configuration app.configure(function() { //set up our express application app.use(express.logger('dev')); //log every request to the console app.use(express.cookieParser()); //read cookies (needed for auth) app.use(express.bodyParser()); //get info from html forms app.set('view engine', 'ejs'); //set up ejs for templating //configuration for passport app.use(express.session({ secret: 'olhosvermdfgytuelhoseasenhaclassica', cookie: { maxAge: 120000 }, store: new MongoStore({ db: 'xYrotr4h', host: 'novus.modulusmongo.net', port: 27017, username: 'gdog', password: 'fakepassowrd123' }) })); //session secret + expiration + store app.use(passport.initialize()); app.use(passport.session()); //persistent login session app.use(flash()); //use connect-flash for flash messages stored in session }); //Set up routes require('./app/routes.js')(app, passport); //launch app.listen(port); console.log("Server listening on port" + port); 

在我新的Passport本地策略中,当用户对数据库成功validation但是导致服务器崩溃时,我尝试使用req.session.regenerate()或req.session.reload()。

以下是我如何定义我的策略:

 //Passport.js sets up our local strategies //imports var LocalStrategy = require('passport-local').Strategy; var User = require('../app/models/user'); //export this as a module since we give it to passport module.exports = function(passport) { //Set up the session for persistent login passport.serializeUser(function(user, done) { done(null, user.id); }); //used to serialize the user passport.deserializeUser(function(id, done) { User.findById(id, function(err, user) { done(err, user); }); }); //setting up local sign up passport.use('local-signup', new LocalStrategy({ //by default, the local strategy uses usernames and password, we will override with email usernameField: 'email', passwordField: 'password', passReqToCallback: true }, function(req, email, password, done) { console.log("Callback ran!"); //asynchronous //User.findOne wont fire unless data is sent back process.nextTick(function() { console.log("I did run!"); //find user whose email is the same as form email // we are checking to see if the user trying to sign up already exists User.findOne({ 'local.email': email }, function(err, user) { //if there any errors, return the errors if (err) { return done(err); } //check to see if there any users already with that email if (user) { return done(null, false, req.flash('signupMessage', 'That email is already taken.')); } else { console.log('New user will be added to the DB!'); //if there is no user with that e-mail, create the user var newUser = new User(); //we set the user's local credentials newUser.local.email = email; newUser.local.password = newUser.generateHash(password); //save the user in the store newUser.save(function(err) { if (err) { throw err; } return done(null, newUser); }); } }); }); })); // ========================================================================= // LOCAL LOGIN ============================================================= // ========================================================================= // we are using named strategies since we have one for login and one for signup // by default, if there was no name, it would just be called 'local' passport.use('local-login', new LocalStrategy({ // by default, local strategy uses username and password, we will override with email usernameField : 'email', passwordField : 'password', passReqToCallback : true // allows us to pass back the entire request to the callback }, function(req, email, password, done) { // callback with email and password from our form // find a user whose email is the same as the forms email // we are checking to see if the user trying to login already exists User.findOne({ 'local.email' : email }, function(err, user) { // if there are any errors, return the error before anything else if (err) return done(err); // if no user is found, return the message if (!user) return done(null, false, req.flash('loginMessage', 'No user found.')); // req.flash is the way to set flashdata using connect-flash // if the user is found but the password is wrong if (!user.validPassword(password)) return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.')); // create the loginMessage and save it to session as flashdata // all is well, return successful user // removing the req.session.regenerate fixes any crashing req.session.regenerate(function(err, done, user){ return done(null, user); }); }); })); }; 

挖完护照和快递图书馆之后,我已经想通了!

 var session = function (req, res) { var temp = req.session.passport; // {user: 1} req.session.regenerate(function(err){ //req.session.passport is now undefined req.session.passport = temp; req.session.save(function(err){ res.send(200); }); }); }; app.post('/login', passport.authenticate('local'), session); 

基本上我让护照先进行身份validation,然后把一个对象附加到req.session.passport上。 Passport使用此对象来查找来自session – > userId的进一步请求的映射。 当您重新生成会话时,req.session.passport对象会丢失。 因此,您必须确保将其转移到新生成的会话并保存。

看起来Jared不想直接支持这个问题 ,因为我不确定我是否同意这个问题#194 ,至less护照应该暴露自己的会话重新生成function。 无论如何,你可以通过replace来解决这个问题:

 req.session.regenerate(function(err, done, user){ return done(null, user); }); 

像这样的东西:

 var passport = req._passport.instance; req.session.regenerate(function(err, done, user) { req.session[passport._key] = {}; req._passport.instance = passport; req._passport.session = req.session[passport._key]; return done(null, user); }); 

我认为你需要replace:

 req.session.regenerate(function(err, done, user){ return done(null, user); }); 

有:

  req.login(user, function(err) { if (err) return res.status(500).send('error'); return done(null,user); }); 

req.login内部调用你的passport.serializeUser()函数。