【问题标题】:Passport Session showing undefined req.user显示未定义 req.user 的护照会话
【发布时间】:2017-05-03 10:23:41
【问题描述】:

当我登录 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);
    });
});

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

编辑2:

用户在序列化中的价值:

{ _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 }

编辑3:

将登录功能更改为:

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!

仍然没有反序列化日志的迹象。

【问题讨论】:

    标签: node.js session passport-local


    【解决方案1】:

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

        /**
         * 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? }
    });
    

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

    【讨论】:

    • 但我确实在 passport.js 中有 deserializeUser ,或者它是不是错了?
    • 此功能需要您已经包含的express-session 的支持。尝试添加上述功能,它应该可以正常工作。尝试使用调试器或简单的日志记录以了解 serializedeserialize 中间件。
    • 更新了我的主题,进行了更改。除非我穿了,否则我完全不明白。
    • userserialize中间件中的值是多少?
    • 更新主题。用户价值。
    【解决方案2】:

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

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

    2. 在一个单独的文件中定义一个快速路由器并将路由挂载到你的 server.js 中

    3. passport.initialize() 和 passport.session() 中间件需要在您定义序列化和反序列化之前附加到您的 express 应用实例。

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

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

    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

    passport-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;

    strategy.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;

    【讨论】:

    • 真的很喜欢这个答案,并且正在尝试将我的大量代码复制到类似的更整洁的文件中。不过,在测试时,我注意到与反序列化相关的 passport-serialize.js 丢失了 ) 和 }。我花了一些时间发现这两个,所以也许值得评论。
    • 我相信这是第二个sn-p。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 2021-03-22
    • 1970-01-01
    • 1970-01-01
    • 2020-03-09
    • 2018-10-24
    相关资源
    最近更新 更多