-
-
Save bobbydavid/2640463 to your computer and use it in GitHub Desktop.
var express = require('express') | |
, http = require('http') | |
, connect = require('connect') | |
, io = require('socket.io'); | |
var app = express(); | |
/* NOTE: We'll need to refer to the sessionStore container later. To | |
* accomplish this, we'll create our own and pass it to Express | |
* rather than letting it create its own. */ | |
var sessionStore = new connect.session.MemoryStore(); | |
/* NOTE: We'll need the site secret later too, so let's factor it out. | |
* The security implications of this are left to the reader. */ | |
var SITE_SECRET = 'I am not wearing any pants'; | |
/* | |
* ... skipping some of your app settings ... | |
*/ | |
app.use(express.bodyParser()); | |
/* NOTE: Pass the cookieParser the site secret. It used to be that | |
* express.session() got the secret, but in Express 3 that's | |
* no longer the case. */ | |
app.use(express.cookieParser(SITE_SECRET); | |
/* NOTE: We'll need to know the key used to store the session, so | |
* we explicitly define what it should be. Also, we pass in | |
* our sessionStore container here. */ | |
app.use(express.session({ | |
key: 'express.sid' | |
, store: sessionStore | |
})); | |
/* | |
* ... skipping the rest of your app settings ... | |
*/ | |
var server = http.createServer(app); | |
server.listen(app.get('port'), function(){ | |
console.log("Express server listening on port " + app.get('port')); | |
}); | |
/** | |
* Socket.io | |
*/ | |
var sio = io.listen(server); | |
sio.set('authorization', function(data, accept){ | |
/* NOTE: To detect which session this socket is associated with, | |
* we need to parse the cookies. */ | |
if (!data.headers.cookie) { | |
return accept('Session cookie required.', false); | |
} | |
/* XXX: Here be hacks! Both of these methods are part of Connect's | |
* private API, meaning there's no guarantee they won't change | |
* even on minor revision changes. Be careful (but still | |
* use this code!) */ | |
/* NOTE: First parse the cookies into a half-formed object. */ | |
data.cookie = require('cookie').parseCookie(data.headers.cookie); | |
/* NOTE: Next, verify the signature of the session cookie. */ | |
data.cookie = require('cookie').parseSignedCookies(data.cookie, SITE_SECRET); | |
/* NOTE: save ourselves a copy of the sessionID. */ | |
data.sessionID = data.cookie['express.sid']; | |
/* NOTE: get the associated session for this ID. If it doesn't exist, | |
* then bail. */ | |
sessionStore.get(data.sessionID, function(err, session){ | |
if (err) { | |
return accept('Error in session store.', false); | |
} else if (!session) { | |
return accept('Session not found.', false); | |
} | |
// success! we're authenticated with a known session. | |
data.session = session; | |
return accept(null, true); | |
}); | |
}); | |
sio.sockets.on('connection', function(socket){ | |
var hs = socket.handshake; | |
console.log('A socket with sessionID '+hs.sessionID+' connected.'); | |
/* NOTE: At this point, you win. You can use hs.sessionID and | |
* hs.session. */ | |
/* NOTE: This function could end here, and everything would be fine. | |
* However, I included this additional mechanism that Daniel | |
* added to keep the session alive by pinging it every 60 | |
* seconds. I don't know how useful this is in the context of | |
* this demo, considering that the sessions aren't going to | |
* expire in the near future. So feel free to not include this: */ | |
var intervalID = setInterval(function(){ | |
hs.session.reload(function(){ | |
hs.session.touch().save(); | |
}); | |
}, 60 * 1000); | |
socket.on('disconnect', function(){ | |
console.log('A socket with sessionID '+hs.sessionID+' disconnected.'); | |
clearInterval(intervalID); | |
}); | |
}); |
Ok, my bad, I was missing the client side impacts... from now it's
var socket = io.connect('http://' + window.location.host + '/namespace');
and after that as usual:
socket.on('connect', function(){
})
instead of the old way
var sio = io.connect();
var socket = sio.socket;
socket.of('/namespace')
What versions of things are you using here, i'm running the latest and I show that the cookie module does't have a parseCookie or parsedSignedCookies method. I must be missing something?
I'm having all sorts of issues with the io authorization cookie. I send that to cookie.parse and node just crashes, and on stop of that it doesn't even give me an error stack dump.
Excellent example! That is what I am looking for.
could not get this to work by copy and paste, data.headers.cookie=undefined in 'authorization'
hey bob and everyone, would you try a tiny module I wrote for the same purpose as this gist?
feedback's appreciated.
why have to pass the secret to the cookieparser instead of the session?
and how can i adapt it to a login system
@wcamarao nice work, you rule.
Thanks mate, this is awesome tweak!
How would you do when using socket namespaces, i.e. the
-way...?
In my case, i finally had it worked, but now it appears my server isn't listening to any socket client-event anymore... (but clients seem to get all server-side event)