admin管理员组

文章数量:1302359

I have an app using passport.js to log in users through facebook, and am attempting to use express-mysql-session to persist their login states. If I don't include the express-mysql-session code, the passport serializeUser and deserializeUser functions hit fine...however when I un-ment the code that attempts to store their session with express-mysql-session, the deserializeUser function doesn't get hit, and the user never gets properly logged in.

server.js file

var express      = require('express');
var mysql        = require('mysql');
var passport     = require('passport');
var session      = require('express-session');
var MySQLStore   = require('express-mysql-session')(session);

if (typeof process.env.OPENSHIFT_MYSQL_DB_HOST === "undefined"){
    var options = {
        host     : 'localhost',
        port     : '3307',
        user     : 'user',
        password : 'password',
        database : 'database',
        socketpath: '/var/run/mysqld/mysqld.sock'
    }
} else { 
    var options = {
        host     : process.env.OPENSHIFT_MYSQL_DB_HOST,
        port     : process.env.OPENSHIFT_MYSQL_DB_PORT,
        user     : process.env.OPENSHIFT_MYSQL_DB_USERNAME,
        password : process.env.OPENSHIFT_MYSQL_DB_PASSWORD,
        database : process.env.OPENSHIFT_APP_NAME,
        socket   : process.env.OPENSHIFT_MYSQL_DB_SOCKET
    }
};    

var connection = mysql.createConnection(options);

var sessionStore = new MySQLStore({
    checkExpirationInterval: 900000,// How frequently expired sessions will be cleared; milliseconds.
    expiration: 86400000,// The maximum age of a valid session; milliseconds.
    createDatabaseTable: false,// Whether or not to create the sessions database table, if one does not already exist.
    connectionLimit: 1,
    schema: {
        tableName: 'LoginRequests',
        columnNames: {
            session_id: 'loginID',
            expires: 'expires',
            data:'data'
        }
    }
}, connection);

 self.initializeServer = function() {
        self.app = module.exports = express();
        self.app.configure(function() {
            self.app.set('views', __dirname + '/public');
            self.app.set('view engine', 'html');
            self.app.engine('html', require('hogan-express'));
            self.app.enable('view cache');
            self.app.use(express.favicon());
            self.app.use(express.logger('dev'));
            self.app.use(express.bodyParser());
            self.app.use(express.methodOverride());
            self.app.use(express.cookieParser('secret'));
            self.app.use(session({
                key: 'session_cookie_name',
                secret: 'secret',
                cookie: {maxAge: 3600000, secure:false},
                store: sessionStore,
                resave: false,
                saveUninitialized: false
            }));
            // required for passport
            self.app.use(passport.initialize());
            self.app.use(passport.session()); // persistent login sessions
            self.app.use(express.static(path.join(__dirname, 'public')));
            self.app.use('/public',express.static(__dirname, '/public'));
            self.app.use(self.app.router);
            //self.app.use(require('stylus').middleware(__dirname + '/public'));


        });

    require('./routes/site.js');  
    require('./config/passport.js')(passport); // pass passport for configuration 

    }

So, if I ment out the "store" option in the session object above, the passport functions get hit. If I leave this line un-mented, the deserializeUser function does not get hit.

Passport functions

passport.serializeUser(function(user, done) {
        console.log('you have been serialized!');
            done(null, user.id);
    });


    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        console.log('you have been deserialized!');
        connection.query("SELECT * FROM Users WHERE id = "+id,function(err,rows){
            done(err, rows[0]);
        });
    });

EDIT

Mor Paz suggested that I include some of the logs from when I run my server with the debug module. Below are the logs right before, and immediately after the user is serialized. The user should be deserialized at some point near this, but never is.

GET /auth/facebook 302 81ms - 412b
express-mysql-session:log Getting session: oNcJ4UapxCY_zKOyfSBTUWaVhaNZuFRq +356ms
you are a user!
you have been serialized!
  express-mysql-session:log Setting session: tgRPY-Mb1VDP2zaSMOFhlf_IWFhVpTia +798ms
  express-mysql-session:log Getting session: tgRPY-Mb1VDP2zaSMOFhlf_IWFhVpTia +6ms
GET /auth/facebook/callback?    code=AQCWPvA5ZRMYoTueW6_wWU49Up5ggjW68ufOtiYkU5IzhRjSNyyWnzlQVprgQo_uubQkEVvNI0yo53ET3cWBnDAHUGmAXPBy_ITEmC-biE2KEGEr0iCm_cqjuG90nnePY-k9U2oFUbX2kvLgMeM0kZ-094EHiU_NJjmAJNj6mzTkSE47935RhJy0Tba_sYS88_C0N3kn5f5kcoTC4KsgW1gBHWWJAwZ68Lj94ffVe2hN97580CtzEpJa0wwQHwTBYfmjQ0NfUdx07m4rXW9R7PR06aHDcUDrYqR9Kb0LWq4sZLbQjV5rI7gzkWG-huhq7IY 302 825ms - 72b
  express-mysql-session:log Setting session: Xo9OjfmJzTFp1CSF6srLi_UyxTCLg-EI +56ms
  express-mysql-session:log Getting session: Xo9OjfmJzTFp1CSF6srLi_UyxTCLg-EI +23ms
  express-mysql-session:log Getting session: Xo9OjfmJzTFp1CSF6srLi_UyxTCLg-EI +2ms
GET /profile 200 84ms - 4.22kb

I have an app using passport.js to log in users through facebook, and am attempting to use express-mysql-session to persist their login states. If I don't include the express-mysql-session code, the passport serializeUser and deserializeUser functions hit fine...however when I un-ment the code that attempts to store their session with express-mysql-session, the deserializeUser function doesn't get hit, and the user never gets properly logged in.

server.js file

var express      = require('express');
var mysql        = require('mysql');
var passport     = require('passport');
var session      = require('express-session');
var MySQLStore   = require('express-mysql-session')(session);

if (typeof process.env.OPENSHIFT_MYSQL_DB_HOST === "undefined"){
    var options = {
        host     : 'localhost',
        port     : '3307',
        user     : 'user',
        password : 'password',
        database : 'database',
        socketpath: '/var/run/mysqld/mysqld.sock'
    }
} else { 
    var options = {
        host     : process.env.OPENSHIFT_MYSQL_DB_HOST,
        port     : process.env.OPENSHIFT_MYSQL_DB_PORT,
        user     : process.env.OPENSHIFT_MYSQL_DB_USERNAME,
        password : process.env.OPENSHIFT_MYSQL_DB_PASSWORD,
        database : process.env.OPENSHIFT_APP_NAME,
        socket   : process.env.OPENSHIFT_MYSQL_DB_SOCKET
    }
};    

var connection = mysql.createConnection(options);

var sessionStore = new MySQLStore({
    checkExpirationInterval: 900000,// How frequently expired sessions will be cleared; milliseconds.
    expiration: 86400000,// The maximum age of a valid session; milliseconds.
    createDatabaseTable: false,// Whether or not to create the sessions database table, if one does not already exist.
    connectionLimit: 1,
    schema: {
        tableName: 'LoginRequests',
        columnNames: {
            session_id: 'loginID',
            expires: 'expires',
            data:'data'
        }
    }
}, connection);

 self.initializeServer = function() {
        self.app = module.exports = express();
        self.app.configure(function() {
            self.app.set('views', __dirname + '/public');
            self.app.set('view engine', 'html');
            self.app.engine('html', require('hogan-express'));
            self.app.enable('view cache');
            self.app.use(express.favicon());
            self.app.use(express.logger('dev'));
            self.app.use(express.bodyParser());
            self.app.use(express.methodOverride());
            self.app.use(express.cookieParser('secret'));
            self.app.use(session({
                key: 'session_cookie_name',
                secret: 'secret',
                cookie: {maxAge: 3600000, secure:false},
                store: sessionStore,
                resave: false,
                saveUninitialized: false
            }));
            // required for passport
            self.app.use(passport.initialize());
            self.app.use(passport.session()); // persistent login sessions
            self.app.use(express.static(path.join(__dirname, 'public')));
            self.app.use('/public',express.static(__dirname, '/public'));
            self.app.use(self.app.router);
            //self.app.use(require('stylus').middleware(__dirname + '/public'));


        });

    require('./routes/site.js');  
    require('./config/passport.js')(passport); // pass passport for configuration 

    }

So, if I ment out the "store" option in the session object above, the passport functions get hit. If I leave this line un-mented, the deserializeUser function does not get hit.

Passport functions

passport.serializeUser(function(user, done) {
        console.log('you have been serialized!');
            done(null, user.id);
    });


    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        console.log('you have been deserialized!');
        connection.query("SELECT * FROM Users WHERE id = "+id,function(err,rows){
            done(err, rows[0]);
        });
    });

EDIT

Mor Paz suggested that I include some of the logs from when I run my server with the debug module. Below are the logs right before, and immediately after the user is serialized. The user should be deserialized at some point near this, but never is.

GET /auth/facebook 302 81ms - 412b
express-mysql-session:log Getting session: oNcJ4UapxCY_zKOyfSBTUWaVhaNZuFRq +356ms
you are a user!
you have been serialized!
  express-mysql-session:log Setting session: tgRPY-Mb1VDP2zaSMOFhlf_IWFhVpTia +798ms
  express-mysql-session:log Getting session: tgRPY-Mb1VDP2zaSMOFhlf_IWFhVpTia +6ms
GET /auth/facebook/callback?    code=AQCWPvA5ZRMYoTueW6_wWU49Up5ggjW68ufOtiYkU5IzhRjSNyyWnzlQVprgQo_uubQkEVvNI0yo53ET3cWBnDAHUGmAXPBy_ITEmC-biE2KEGEr0iCm_cqjuG90nnePY-k9U2oFUbX2kvLgMeM0kZ-094EHiU_NJjmAJNj6mzTkSE47935RhJy0Tba_sYS88_C0N3kn5f5kcoTC4KsgW1gBHWWJAwZ68Lj94ffVe2hN97580CtzEpJa0wwQHwTBYfmjQ0NfUdx07m4rXW9R7PR06aHDcUDrYqR9Kb0LWq4sZLbQjV5rI7gzkWG-huhq7IY 302 825ms - 72b
  express-mysql-session:log Setting session: Xo9OjfmJzTFp1CSF6srLi_UyxTCLg-EI +56ms
  express-mysql-session:log Getting session: Xo9OjfmJzTFp1CSF6srLi_UyxTCLg-EI +23ms
  express-mysql-session:log Getting session: Xo9OjfmJzTFp1CSF6srLi_UyxTCLg-EI +2ms
GET /profile 200 84ms - 4.22kb
Share edited Mar 10, 2017 at 20:17 m87 4,5133 gold badges18 silver badges31 bronze badges asked Sep 28, 2016 at 23:07 user2796352user2796352 9643 gold badges14 silver badges23 bronze badges 11
  • 1 Can you add the logs from Node? The express-mysql-session module should output plenty of logging info when running in DEBUG – Mor Paz Commented Oct 3, 2016 at 12:20
  • How do I run node in DEBUG mode? – user2796352 Commented Oct 4, 2016 at 23:09
  • 2 Are you sure the connection to mysql is established successfully? Use connection.connect() and add a callback with an err argument to the call to connect to make sure the connection is established without a problem. *PS: Are you actually using port 3307 too? because mysql's default is 3306 – Omar A Commented Oct 5, 2016 at 15:55
  • 3 I've got these modules working together fine using these versions: express 3.0, passport 0.3, express-session 1.11, express-mysql-session 1.2.I'm not able to replicate your error but I'm missing the version information, as well as your passport strategies for logging in and out. Can you provide a gist or github repo where the error can be replicated? – Larry Turtis Commented Oct 16, 2016 at 20:50
  • 2 @user2796352 Did you found a solution for this problem? – Sagar V Commented Jul 7, 2017 at 6:52
 |  Show 6 more ments

1 Answer 1

Reset to default 1

It was impossible to replicate the problem, so I prepared a working example. [Github repo.]

Its crafted for Openshift, since I saw the usage of its environment variables (it can be adapted with ease for other use cases).

I did some modifications to the original concept :

  1. Replaced the old, deprecated (express) bundled middleware usages.
  2. Using a Class instead of the self = this concept
  3. Using Github instead of Facebook for the user login...
  4. Included some basic functions to include new users to the db
  5. Missing some original modules (can be included with ease)

I hope it can be useful as a starting point.

 // .: DB Configuration :.
const mysql = require('mysql'); 
var dbconf = {host:process.env.OPENSHIFT_MYSQL_DB_HOST,port:process.env.OPENSHIFT_MYSQL_DB_PORT,user:process.env.OPENSHIFT_MYSQL_DB_USERNAME,password:process.env.OPENSHIFT_MYSQL_DB_PASSWORD,database:process.env.OPENSHIFT_APP_NAME,socket:process.env.OPENSHIFT_MYSQL_DB_SOCKET}}    
const dbconn = mysql.createConnection(dbconf); /*or create a pool*/ dbconn.connect();
// .: Express & Other Middleware Modules :.
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var cookieParser = require('cookie-parser');
var serveStatic = require('serve-static');
// .: Sessions :.
var passport = require('passport');
var GitHubStrategy = require('passport-github2');
var session = require('express-session');
var MySQLStore = require('express-mysql-session')(session);
var sessionStoreConf = {
  connectionLimit:1,checkExpirationInterval:900000,expiration:86400000,
  createDatabaseTable:true,schema:{tableName:'LoginRequests',columnNames:{session_id:'loginID',expires:'expires',data:'data'}}
};
var sessionStore = new MySQLStore(sessionStoreConf,dbconn);
// .: Server (class) :.
class Server {
  constructor(port, ip){
    this.app = express();
    this.app.use(cookieParser('secret'));
    this.app.use(session({
      key:'session_cookie_name',
      secret:'secret',
      cookie:{maxAge:3600000,secure:false},
      store: sessionStore,
      resave:false,
      saveUninitialized:false
    }));
    this.app.use(passport.initialize());
    this.app.use(passport.session());
    this.app.use(serveStatic(path.join(__dirname,'public')))
    this.app.listen(port,ip,function(){console.log('[i] Application worker started.');});
    //require('./routes/site.js'); //~Example (routes/site.js) :
      this.app.get("/",function(req,res){res.send("<a href='./auth/github'>Click here to login (GitHub)</a>");})
      this.app.get('/auth/github',passport.authenticate('github',{scope:['user:email']}));
      this.app.get('/auth/github/callback',passport.authenticate('github',{failureRedirect:'/'}),function(req,res){res.redirect('/success');});
      // route for valid logins
      this.app.get('/success', function(req, res){ 
        if(req.user){ console.log(req.user);  res.send(req.user); }
        else{ res.redirect('/login'); }
      });
      // route to check the sessionStore table entries in the browser
      this.app.get('/sessions',function(req,res){
        dbconn.query("SELECT * FROM LoginRequests",function(err,rows){
          if(err){console.log(err);}else{
            if(rows.length!=0){
              res.send(JSON.stringify(rows));
              console.log(rows);
            }else{res.send("No LoginRequests found");}
          }
        });
      });
    //require('./config/passport.js')(passport);  //~Example (config/passport.js) :
      passport.use(new GitHubStrategy(
        {clientID:"clientID",clientSecret:"clientSecret",callbackURL:"callbackURL"},
        function(token, tokenSecret, user, cb){CheckUser('github',user,cb);}
      ));
    }
}
const server = new Server(process.env.OPENSHIFT_NODEJS_PORT,process.env.OPENSHIFT_NODEJS_IP);
// .: Passport : Serialize & Deserialize User :.
passport.serializeUser(function(user, done){
 console.log('[passport] serializeUser');
 done(null,user.id);
});
passport.deserializeUser(function(id, done) {
 console.log('[passport] deserializeUser');
  dbconn.query("SELECT * FROM Users WHERE id=?",[id],function(err,rows){
  if(err){console.log(err);}else{
    if(rows.length!=0){ done(err,rows[0]); }
    else{ done(err,null); }
  }
 });
});

//:Check if user exists:
function CheckUser(platform,user,cb){
  dbconn.query("SELECT * FROM Users WHERE id=?",[user.id],function(err,rows){
  if(err){console.log(err); cb(err,null);}else{
    if(rows.length!=0){cb(null,user);}
    else{CreateUser(platform,user,cb);}
    }
  });
}
  //:Create new user:
function CreateUser(platform,user,cb){
  switch(platform){
    case "github": 
      var newUserObj  = {id:user.id,platform:platform,email:user.emails[0].value};
      dbconn.query("INSERT INTO Users SET ?",newUserObj,function(err){
        if(err){console.log(err); cb(err,null);}else{cb(null,user);}
      });
    break;
    default: console.log("[error] (createUser) : platform not implemented :",platform); cb(err,null); break;
  }
}

本文标签: javascriptExpressmysqlsession preventing passport deserializeUser from runningStack Overflow