Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

Session Management in Nodejs

4.75/5 (10 votes)
11 May 2012CPOL2 min read 52.4K  
In this article we're gonna create a simple WebSocket session manager module for Nodejs to help us out with our next projects.

Introduction

As you may know, we can run a WebSocket server through Nodejs using the Socket.io module. The main issue in a socket.io server is how to manage sessions and users. In this article we are going to create a simple Nodejs module to help us out with this issue.

 

Here we go!

Socket IO

Whenever a user connects to a Socket.io Server, the server will create a session with a unique Id which is essential for unicasting. Here is a sample code which show’s you, how socket.io works; but for more information go to socket.io

JavaScript
// Load an instance of the Socket.io module
// It will listen to port no. 3000 for connections
var io = require('socket.io').listen(3000);

// Tells the application what to do whenever
// a new client connects to the server
io.sockets.on('connection', function (socket) {
  // Send some data to the user
  socket.emit('news', { hello: 'world' });

  // Listen to the event named "my other event"
  socket.on('my other event', function (data) {
    // Log the recieved data in the application console
    console.log(data);
  });
});

In this example we are just going to store a username, user id and role for each session.
Here is our Roles list: 

JavaScript
var userRoles = {
  Admin: "administrator",
  User: "user",
  Supervisor: "supervisor"
};

Now, let’s write our session manager class and then turn it into a Nodejs Module.
sessionManagement.js:

JavaScript
var sessionManagement = {
  
};

For such a module, we’ll need to do the followings:

  • Add/Remove user
  • Find session by id
  • Find session by user id
  • Check Permission

At first we need to store the data. I prefer using a simple array because they are fast and easy to use.
You might ask “What if server falls?!” Well, I say that if server falls all sessions are lost and remade; but if you need the data for any reason, I suggest mongoose, which is a MongoDB module for Nodejs.

I’ll put the array outside of the class scope for more security.

JavaScript
var sessions = [];

var sessionManagement = {
  
};

Except then mentioned methods, we’ll need a method to find the index of a given user Id, so we won’t need to code it each single time:

JavaScript
function(sessionId) {
  for(var i in sessions) {
      if(sessions[i].sessionId == sessionId)
          return i;
  }
}

Here is our complete script (sessionManagement.js):

JavaScript
var sessions = [];

//User roles list
var userRoles = {
  Admin: "administrator",
  User: "user",
  Supervisor: "supervisor"
};

var sessionManagement = {
  indexOf: function(sessionId) {
    for(var i in sessions) {
        if(sessions[i].sessionId == sessionId)
            return i;
    }
    
    return null;
  },
  indexOfUser: function(userId) {
    for(var i in sessions) {
        if(sessions[i].userId == userId)
            return i;
    }
    
    return null;
  },
  
  add: function(sessionData) {
    sessions.push(sessionData);
  },
  remove: function(sessionId) {
    var index = this.indexOf(sessionId);
    if(index != null) {
        sessions.splice(index, 1);
    } else {
        return null;
    }
  },
  removeByUserId: function(userId) {
    var index = this.indexOf(userId);
    if(index != null) {
        sessions.splice(index, 1);
    } else {
        return null;
    }
  },
  
  getSessionById: function(userId) {
    var index = this.indexOfUser(userId);
    if(index != null) {
        return sessions[index];
    } else {
        return null;
    }
  },
  getSessionByUserId: function(sessionId) {
    var index = this.indexOfUser(userId);
    if(index != null) {
        return sessions[index];
    } else {
        return null;
    }
  },
  
  isAdmin: function(userId) {
    var index = this.indexOfUser(userId);
    if(index != null) {
        if(users[index].role == userRoles.Admin) {
            return true;
        } else {
            return false;
        }
    } else {
        return null;
    }
  },
  getUsersByRole: function(role) {
    var usersByRole = [];
    for(var i in users) {
        if(users[i].role == role)
            usersByRole.push(users[i]);
    }
    
    return usersByRole;
  }
};

Now, it’s time to convert it to a Nodejs Module…
As you can see in Nodejs manual, we must add any desired object to the module.exports object in order to use it in another module or script. So we’ll just need to assign our class to this variable:

JavaScript
module.exports = sessionManagement;

 

There We Are!

Now we can use the module in any desired script by simply putting the sessionManagement.js in our application directory or the node_modules directory.

 

Sample usage:
JavaScript
var sessionMgm = require("sessionManagement");
	
io.sockets.on('connection', function (socket) {
    socket.on('setUserInfo', function (data) {
        var sess = new Object();
        sess.sessionId = socket.id;
        sess.userId = data.userId;
        sess.username = data.username;
        sess.role = data.role;
        sessionMgm.add(sess);
    });
    
    socket.on('sendPm', function(data) {
        if(data != null) {
            var user = sessionMgm.getSessionByUserId(data.userId);
            if(user != null) {
                io.sockets.socket(user.sessionId).emit('newMessage', data.message);
            } else {
                var sysMsg = {type: "error", message: "User not found!"};
                socket.emit('systemMessage', sysMsg);
            }
        }
    });
    
    socket.on('disconnect', function() {
        sessionMgm.remove(socket.id);
    });
}

 

Conclusion

Socket.io dedicates a unique id to each session. To send an event directly to a specific user, we need to know their session id. We wrote a class to manage these sessions and then turned it to a Nodejs module to use it simpler in our next applications. Using this module we can simply manage the users by their session id, user id or role.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)