Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Something weird about express session store

If I store an object in session like this:

user.name = "Kelvin"; // user is an object pass by "mongoose" findOne's callback.
req.session.user = user; 
console.log(req.session.user.name); // Kelvin

and after that, I access "user" in other routes of express:

app.get("/somepath", function(req, resp) {
    console.log(req.session.user.name); // undefined
});

I want to know why req.session.user.name is undefined besides the function I set it?

like image 522
Kevin Avatar asked Apr 22 '12 05:04

Kevin


1 Answers

After looking into mongoose source code I can say that this is because how mongoose models and session works. When you call req.session.user = user then req.session.user points to the object but actually the data needs to be stored somewhere (like memory or Redis).

In order to do that Express calls JSON.stringify(sess) and string is stored in memory. Here's where mongoose enters. Models are constructed in such a way, that when you stringify them only attributes predefined in Schema are included. So when you set req.session.user = user Express stringifies user (you loose name attribute) and saves the data. When you call req.session.user in another route Express parses stringified data and you obtain object without name attribute.

Now how to fix this? There are several ways.

  • Add name attribute to the Schema;
  • Define new literal object for user:

    var newuser = { id: user.id, name : "Kelvin", pwd: user.pwd, etc. }; req.session.user = newuser;

  • Store name in another field: req.session.name = "Kelvin"; (the best solution imho)

By the way: You shouldn't hold the user object in session. What if some other user like administrator makes changes to the user object? You won't see them at all. I advice holding only the id of the user in session and make custom middleware to load user from DB and store it in request object.

like image 122
freakish Avatar answered Sep 19 '22 23:09

freakish