Passport Session显示未定义的req.user

时间:2017-05-03 10:23:41

标签: node.js session passport-local

当我正确地显示req.user时,但导航到/test后,req.user为undefined

为什么?

server.js

var express    = require('express');        // call express
var app        = express();                 // define our app using express
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var session      = require('express-session');
var router = express.Router();
var Account = require('src/app/models/Users.js');
var Core = require('/src/app/gamemodels/core');
// Init passport authentication
var passport = require('passport');
var Strategy = require('passport-local').Strategy;
require('/src/config/passport')(passport);
var cookieParser = require('cookie-parser')



// required for passport session

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
mongoose.connect('DB');
app.use(cookieParser()) // required before session.

app.use(session({ secret: 'xxxx' }));
app.use(passport.initialize());
app.use(passport.session());






var port = process.env.PORT || 3000;        // set our port


// test route to make sure everything is working (accessed at GET http://localhost:8080/api)
router.get('/', function(req, res) {
    res.json({ text: 'hooray! welcome to our api!' });
});


router.get('/test', function(req,res) {
    console.log(req);
    console.log(req.user);
    res.json(req.user);
});


router.post('/signup', passport.authenticate('local-signup', {
    successRedirect : '/profile', // redirect to the secure profile section
    failureRedirect : '/signup', // redirect back to the signup page if there is an error
}));

router.post('/login', passport.authenticate('local-login'), function(req, res) {

    console.log("executed login!");
    console.log(req.user);
    req.session.user = req.user;

});


});
*/



// more routes for our API will happen here

// REGISTER OUR ROUTES -------------------------------
// all of our routes will be prefixed with /api
app.use('/api', router);

// START THE SERVER
// =============================================================================
app.listen(port);
console.log('Magic happens on port ' + port);

护照js:

// config/passport.js

// load all the things we need
var LocalStrategy   = require('passport-local').Strategy;

// load up the user model
var Account = require('src/app/models/Users.js');

// expose this function to our app using module.exports
module.exports = function(passport) {

    passport.serializeUser(function(user, done) {
        done(null, user);
    });

    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        Account.findById(id, function(err, user) {
            done(err, user);
        });
    });

    passport.use('local-login', new LocalStrategy({
            // by default, local strategy uses username and password, we will override with email
            usernameField : 'username',
            passwordField : 'password',
            passReqToCallback : true // allows us to pass back the entire request to the callback
        },
        function(req, username, password, done) { // callback with email and password from our form
            console.log("doing local login");
            // 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
            Account.findOne({ 'username' :  username }, function(err, user) {
                var thisuser = user;
                console.log("query account is done");
                // if there are any errors, return the error before anything else
                if (err) {
                    console.log("error occured");
                    return done(err);
                }

                console.log("if user exist check");


                // if no user is found, return the message
                if (!user)
                    return done(null, false,'No user found.'); // req.flash is the way to set flashdata using connect-flash


                console.log("checking password");
                // if the user is found but the password is wrong
                if (!user.validPassword(password)) {
                    console.log("password is not valid");
                    return done(null, false, 'Oops! Wrong password.'); // create the loginMessage and save it to session as flashdata

                }
                console.log("all good! logging in!");


                req.login(thisuser, function(error) {
                    if (error) return next(error);
                    console.log("Request Login supossedly successful.");
                });

                // all is well, return successful user
                return done(null, thisuser);
            });

        }));

    passport.use('local-signup', 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, username, password, done) {
            process.nextTick(function() {
                    console.log("doing local signup");
                // 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
                Account.findOne({ 'username' :  username }, function(err, user) {
                    // if there are any errors, return the error
                    if (err)
                        return done(err);

                    // check to see if theres already a user with that email
                    if (user) {
                        return done(null, false, 'That username is already taken.');
                    } else {

                        var newUser            = new Account();

                        // set the user's local credentials
                        newUser.username    = username;
                        newUser.password = newUser.encryptPassword(password);

                        // save the user
                        newUser.save(function(err) {
                            if (err)
                                throw err;
                            return done(null, newUser);
                        });
                    }

                });

            });

        }));

};

EDIT1:

将passport.js序列化函数和反序列化函数更改为以下内容:

passport.serializeUser(function(user, done) {
    done(null, user.username);
});

// used to deserialize the user
passport.deserializeUser(function(username, done) {
    Account.findOne({'username': username}, function(err, user) {
        done(err, user);
    });
});

仍然没有任何区别。尚未定义。

EDIT2:

序列化中用户的值:

{ _id: 5909a6c0c5a41d13340ecf94,
  password: '$2a$10$tuca/t4HJex8Ucx878ReOesICV6oJoS3AgYc.LxQqCwKSV8I3PenC',
  username: 'admin',
  __v: 0,
  inFamily: false,
  bank: 500,
  cash: 2500,
  xp: 0,
  rank: 1,
  bullets: 0,
  location: 1,
  permission: 0,
  health: 100 }

EDIT3:

将登录功能更改为:

router.post('/login', passport.authenticate('local-login'), function(req, res) {

    console.log("executed login!");
    console.log(req.user);
    req.session.user = req.user;
    req.logIn(req.user, function (err) {
        if (err) {
            return next(err);
        }

    });

});

服务器日志响应:

doing local login
query account is done
if user exist check
checking password
all good! logging in!
serializing!
Request Login supossedly successful.
serializing!
executed login!
{ _id: 5909a6c0c5a41d13340ecf94,
  password: '$2a$10$tuca/t4HJex8Ucx878ReOesICV6oJoS3AgYc.LxQqCwKSV8I3PenC',
  username: 'admin',
  __v: 0,
  inFamily: false,
  bank: 500,
  cash: 2500,
  xp: 0,
  rank: 1,
  bullets: 0,
  location: 1,
  permission: 0,
  health: 100 }
serializing!

仍然无法反序列化日志。

2 个答案:

答案 0 :(得分:3)

原因是您在反序列化部分缺少。

    /**
     * Each subsequent request will contain a  unique 
     * cookie that identifies the session. In order to support login sessions, 
     * Passport will serialize and deserialize user instances to and from the session.
     */
    passport.serializeUser(function (user, done) {
        done(null, user.username);
    });

    passport.deserializeUser(function (username, done) {
        /**
         * Necessary to populate the express request object with
         * the 'user' key
         * Requires(*):
         *  - session support with express
         *  - call to logIn from passport.auth)enticate if using authenticate
         *   callback.
         */
        // TODO: Verify if username exists
        done(null, username);
    });

因此,在对用户进行身份验证或req.isAuthenticated()为真之后,将调用反序列化中间件函数,并在您的情况下使用usernamereq.user更新请求对象。

参考:

由于您使用自定义回调来处理成功或失败,因此应用程序负责通过调用req.logIn来建立会话。因此,在用户通过身份验证后,添加

req.logIn(user, function (err) {
    if (err) { return next(err); }
    return { // Do a redirect perhaps? }
});

请参阅参考链接中的自定义回调部分,我给了你。

答案 1 :(得分:2)

在护照对象上定义方法和中间件时,顺序很重要。你的代码很纠结。稍微脱钩会在这里走很长的路。

  1. 将所有策略逻辑移出server.js和passport.js。把它放在自己的文件集中。此外,您不需要在服务器文件中包含基本策略。

  2. 在单独的文件中定义快速路由器并在您的server.js中挂载路由

  3. passport.initialize()和passport.session()中间件需要附加到您的快速应用实例,然后再定义序列化和反序列化

  4. 无需设置req.session.user,这会破坏在会话中仅存储用户ID的目的。在每个表达请求时,一旦通过读取req.session.passport.user中的id反序列化用户,您就可以将整个用户帐户文档加载到req.user中,并且可以直接从req访问所有用户数据。用户。

  5. 如果您使用预先打包的护照策略构造函数调用done(),则无需在任何地方调用req.login。

  6. server.js

    
    
    //express, body parser, express session, etc
    
    const app = express();
    const passport = require('passport');
    const user = require('./passport-serialize');
    const routes = require('./routes');
    
    //lots of middleware
    
    //session middleware
    
    app.use(passport.initialize());
    app.use(passport.session());
    
    passport.serializeUser(user.serialize);
    
    passport.deserializeUser(user.deserialize);
    
    app.use('/api', routes);
    
    //actual server, more stuff
    
    
    

    护照serialize.js

    
    
    //include Account model
    
    const user = {
      serialize: (user, done) => {
        done(null, user.username)
      },
      deserialize: (username, done) => {
        Account.findOne({'username': username}, function(err, user) {
        done(err, user);
      }
    }
    
    module.exports = user;
    
    
    

    routes.js

    
    
    const express = require('express');
    
    const router = new express.Router();
    
    const passport = require('./strategies');
    
    //many routes
    
    router.post('/login', passport.authenticate('local-login'), function(req, res) {
      console.log("executed login!");
      console.log(req.user);
    });
    
    router.get('/test', function(req, res) {
      console.log(req.user);
      res.json(req.user);
    });
    
    
    
    module.exports = router;
    
    
    

    strategies.js

    
    
    const passport = require('passport');
    const LocalStrategy = require('whatever the package is');
    //Account model
    
    passport.use('local-login', new LocalStrategy({
      // by default, local strategy uses username and password, we will override with email
      usernameField : 'username',
      passwordField : 'password',
      passReqToCallback : true // allows us to pass back the entire request to the callback
    },  function(req, username, password, done) { // callback with email and password from our form
      console.log("doing local login");
      // 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
      Account.findOne({ 'username' :  username }, function(err, user) {
        var thisuser = user;
        console.log("query account is done");
        // if there are any errors, return the error before anything else
        if (err) {
          console.log("error occured");
          return done(err);
        }
        console.log("if user exist check");
    
        // if no user is found, return the message
        if (!user)
          return done(null, false,'No user found.'); 
          // req.flash is the way to set flashdata using connect-flash
          console.log("checking password");
          // if the user is found but the password is wrong
        } else if (!user.validPassword(password)) {
          console.log("password is not valid");
          return done(null, false, 'Oops! Wrong password.'); 
          // create the loginMessage and save it to session as flashdata
        }
        console.log("all good! logging in!");
        // all is well, return successful user
        return done(null, thisuser);
      });
    }));
            
     module.exports = passport;