简体   繁体   中英

req.session.passport is empty: req.user undefined

I've asked a similar question before, but I noticed it was in the Javascript section. I have more specific ideas of what might be going wrong now, as well.

Basically, req.session.passport is empty in my logs. Whenever I start navigating around my site, req.user becomes undefined because the session doesn't have Passport's logged in user anymore.

I would like to know if anyone knows how to solve this? Maybe it's just an error in the configuration of Passport, or the entire Express setup?

App.js:

var express = require("express"),
    bodyParser = require("body-parser"),
    mongodb = require("mongodb"),
    mongoose = require("mongoose"),
    uriUtil = require("mongodb-uri"),
    morgan = require("morgan"),
    session = require("express-session"),
    passport = require("passport"),
    flash = require("connect-flash"),
    ip = "hidden",
    port = process.env.PORT || 80

var app = express()
app.disable("x-powered-by")
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
    extended: true
}))

app.use(morgan("dev")); // log every request to the console

// required for passport
app.use(session({
    secret: "hidden",
    key: 'asdasdasd', 
    cookie: { maxAge: 60000, secure: false },
    resave: true,
    saveUninitialized: false
})); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session

app.set("view engine", "jade")
app.use(express.static(__dirname + "/views"))

require("./includes/passport")(passport)
require("./includes/subject")
require("./includes/user")

Passport.js:

var LocalStrategy = require("passport-local").Strategy,
    User = require("./user"),
    bCrypt = require('bcrypt-nodejs')

module.exports = function(passport) {

    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        done(null, user._id);
    });

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

    // =========================================================================
    // LOCAL SIGNUP ============================================================
    // =========================================================================
    // 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('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, email, password, done) {

        // asynchronous
        // User.findOne wont fire unless data is sent back
        process.nextTick(function() {

            // 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({ "email" :  email }, 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, req.flash("message", "Dit e-mail-adres is al bezet"));
                } else {

                    // if there is no user with that email
                    // create the user
                    var newUser = new User();

                    // set the user's local credentials
                    newUser.email = email;
                    newUser.password = createHash(password);
                    newUser.firstname = req.param('firstname');
                    newUser.lastname = req.param('surname');
                    newUser.year = parseInt(req.param('year'));
                    newUser.study = req.param('study');
                    newUser.courses = req.param('courses');
                    newUser.phone = req.param('phone');
                    newUser.availability = req.param('availability');
                    newUser.description = req.param('descText');

                    // save the user
                    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("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({ "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) {
                console.log('No user found with email ' + email)
                return done(null, false, req.flash('message', 'Gebruiker niet gevonden')); // req.flash is the way to set flashdata using connect-flash
            }

            if (!isValidPassword(user, password)){
                console.log('Incorrect Password');
                return done(null, false, req.flash('message', 'Onjuist wachtwoord')); // redirect back to login page
            }

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

    }));

    var isValidPassword = function(user, password){
        return bCrypt.compareSync(password, user.password);
    }

    // Generates hash using bCrypt
    var createHash = function(password){
        return bCrypt.hashSync(password, bCrypt.genSaltSync(10), null);
    }

};

The routes:

api.post("/signup", passport.authenticate("signup", {
    successRedirect: "/profile",
    failureRedirect: "/",
    failureFlash: true
}))

api.post("/login", passport.authenticate("login", {
    successRedirect: "/profile",
    failureRedirect: "/login"//,
    failureFlash: true
}))

router.get("/", function(req, res) {
    // serve index.html

    res.render("index", {
        title: 'Home',
        user: req.user,
        message: req.flash("message") 
    })
})

It works on the page that is accessed directly after logging in, which I control as follows:

router.get("/profile", isLoggedIn, function(req, res) {
    res.render("profile", {
        title: 'Gebruikersprofiel van ' + req.user.firstname + " " + req.user.lastname,
        user: req.user // get the user out of session and pass to template
    })
})
function isLoggedIn(req, res, next) {
    console.log(req.session)
    // if user is authenticated in the session, carry on
    if (req.isAuthenticated())
        return next()

    // if they aren't redirect them to the home page
    res.redirect("/login")
}

So far, I've tried adding middleware to add req.user to req.session, and doing the same thing in the login POST. Also I've tried changing the order in which I initialize the middleware in app.js. I am using the new express-session version, without CookieParser, as I read that CookieParser is no longer needed.

If anyone can help me in any way, it would be much appreciated! I've been stuck for a while (as have others).

The problem was not anything I did wrong in setting up the session, or Passport in general, but rather in my links. I read somewhere that someone was accidentally working in multiple domains (his platform was apparently multi-server), and that made me look through my links this morning.

Apparently, I was linking to my website with www. prefixed, but the session was initialized where there was no www. in front of the URL. I saw this in the cookies. The solution was, therefore, to link through the website consistently, either having www. prefixed everywhere or nowhere.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM