Skip to content

Instantly share code, notes, and snippets.

@MiLk
Created August 2, 2012 07:35
Show Gist options
  • Select an option

  • Save MiLk/3234912 to your computer and use it in GitHub Desktop.

Select an option

Save MiLk/3234912 to your computer and use it in GitHub Desktop.
Authentification par cookie avec Express.js 3 & socket.io
var express = require('express')
, app = express.createServer()
, cookie = require('cookie')
, io = require('socket.io')
, _ = require('underscore')._
, redis = require('redis')
, dbmysql = require('db-mysql')
, mysql = new dbmysql.Database({
hostname: '',
port: 3306,
user: '',
password: '',
database: '',
initCommand: 'SET NAMES utf8'
}).on('error', function(error) {
console.log('ERROR: ' + error);
}).on('ready', function(server) {
console.log('Connected to ' + server.hostname + ' (' + server.version + ')');
});
var sessionStore = new express.session.MemoryStore({ reapInterval: 60000 * 10 });
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.cookieParser());
app.use(express.session({
"secret": "secret",
"store": sessionStore,
"key": 'express.sid',
}));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
function requireLogin (req, res, next) {
if (req.session.username) {
// User is authenticated, let him in
next();
} else {
// Otherwise, we redirect him to login form
res.redirect("/login");
}
}
function validateLogin(username,password,callback) {
mysql.connect(function(err){
if(err) { console.log(err); callback(false,null); }
var res = mysql.query('SELECT * FROM sf_guard_user WHERE username LIKE "'+mysql.escape(username)+'" AND password LIKE SHA1(CONCAT(salt,"'+mysql.escape(password)+'"))')
.execute(function(error, rows, cols) {
if (error) {
console.log('ERROR: ' + error);
callback(false,null);
}
callback(_.size(rows) == 1, rows[0]);
});
});
}
app.get("/login", function (req, res) {
res.render("login", { "username": req.session.username, "error": null });
});
app.post("/login", function (req, res) {
var options = { "username": req.body.username, "error": null };
if (!req.body.username) {
options.error = "User name is required";
res.render("login", options);
} else if (!req.body.password) {
options.error = "Password is required";
res.render("login",options);
} else if (req.body.username == req.session.username) {
// User has not changed username, accept it as-is
res.redirect("/");
} else if (!req.body.username.match(/^[a-zA-Z0-9\-_]{3,}$/)) {
options.error = "User name must have at least 3 alphanumeric characters";
res.render("login", options);
} else {
validateLogin(req.body.username,req.body.password, function(auth,account){
if(!auth)
{
options.error = "Username or password is invalid.";
res.render("login", options);
} else {
req.session.username = req.body.username;
req.session.account = account.id;
res.redirect("/");
}
});
}
});
app.get('/', [requireLogin], function(req, res){
res.render('index');
});
io = io.listen(app.listen(process.env.npm_package_config_port || 3000, function(){
console.log("Express server listening on port %d in %s mode", process.env.npm_package_config_port || 3000, app.settings.env);
}));
var RedisStore = require('socket.io/lib/stores/redis')
, pub = redis.createClient()
, sub = redis.createClient()
, client = redis.createClient();
io.configure(function(){
io.enable('browser client minification'); // send minified client
io.enable('browser client etag'); // apply etag caching logic based on version number
io.enable('browser client gzip'); // gzip the file
io.set('log level', 1); // reduce logging
io.set('transports', [ // enable all transports (optional if you want flashsocket)
'websocket'
// , 'flashsocket'
, 'htmlfile'
, 'xhr-polling'
, 'jsonp-polling'
]);
io.set('store', new RedisStore({
redisPub : pub
, redisSub : sub
, redisClient : client
}));
});
io.sockets.authorization(function (handshakeData, callback) {
// Read cookies from handshake headers
var cookies = cookie.parse(handshakeData.headers.cookie);
// We're now able to retrieve session ID
var sessionID = cookies['express.sid'];
// No session? Refuse connection
if (!sessionID) {
callback('No session', false);
} else {
// Store session ID in handshake data, we'll use it later to associate
// session with open sockets
handshakeData.sessionID = sessionID;
// On récupère la session utilisateur, et on en extrait son username
// Hack pour avoir le bon format de sessionID
var mySessionID = handshakeData.mySessionID = sessionID.substr(2,sessionID.indexOf('.')-2);
sessionStore.get(mySessionID, function (err, session) {
if (!err && session && session.username) {
// On stocke ce username dans les données de l'authentification, pour réutilisation directe plus tard
handshakeData.username = session.username;
// OK, on accepte la connexion
callback(null, true);
} else {
// Session incomplète, ou non trouvée
callback(err || 'User not authenticated', false);
}
});
}
});
var connections = {};
io.sockets.on('connection', function (socket) {
var sessionID = socket.handshake.sessionID; // Store session ID from handshake
console.log(socket.handshake);
// this is required if we want to access this data when user leaves, as handshake is
// not available in "disconnect" event.
socket.set('username', socket.handshake.username, function(){
console.log(socket.handshake.username + ' connected !');
}); // Same here, to allow event "bye" with username
if ('undefined' == typeof connections[sessionID]) {
connections[sessionID] = { "length": 0 };
// First connection
}
// Add connection to pool
connections[sessionID][socket.id] = socket;
connections[sessionID].length ++;
// do sth
socket.on('disconnect', function () {
// do sth
var userConnections = connections[sessionID];
if (userConnections.length && userConnections[socket.id]) {
// Forget this socket
userConnections.length --;
delete userConnections[socket.id];
}
if (userConnections.length == 0) {
// No more active sockets for this user: say bye
console.log(socket.get('username') + ' disconnected !');
}
});
socket.on('error', function(err) {
console.log(err);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment