socket.io and session?
I'm using express framework. I want to reach session data from socket.io. I tried express dynamicHelpers with client.listener.server.dynamicViewHelpers data, but i开发者_运维问答 can't get session data. Is there a simple way to do this? Please see the code
app.listen(3000);
var io = require('socket.io');
var io = io.listen(app);
io.on('connection', function(client){
// I want to use session data here
client.on('message', function(message){
// or here
});
client.on('disconnect', function(){
// or here
});
});
This won't work for sockets going over the flashsocket transport (it doesn't send the server the needed cookies) but it reliably works for everything else. I just disable the flashsocket transport in my code.
To make it work, in the express/connect side, I explicitly define the session store so I can use it inside socket:
MemoryStore = require('connect/middleware/session/memory'),
var session_store = new MemoryStore();
app.configure(function () {
app.use(express.session({ store: session_store }));
});
Then inside my socket code, I include the connect framework so I can use its cookie parsing to retrieve the connect.sid from the cookies. I then look up the session in the session store that has that connect.sid like so:
var connect = require('connect');
io.on('connection', function(socket_client) {
var cookie_string = socket_client.request.headers.cookie;
var parsed_cookies = connect.utils.parseCookie(cookie_string);
var connect_sid = parsed_cookies['connect.sid'];
if (connect_sid) {
session_store.get(connect_sid, function (error, session) {
//HOORAY NOW YOU'VE GOT THE SESSION OBJECT!!!!
});
}
});
You can then use the session as needed.
The Socket.IO-sessions module solution exposes the app to XSS attacks by exposing the session ID at the client (scripting) level.
Check this solution instead (for Socket.IO >= v0.7). See docs here.
I suggest not to entirely reinvent the wheel. The tools you need is already an npm package.I think this is what you need: session.socket.io I am using it in these days and it will be very helpful I guess!! Linking the express-session to the socket.io layer will have so many advantages!
Edit: After trying some modules that didn't work, I've actually gone and written my own library to do this. Shameless plug: go check it out at https://github.com/aviddiviner/Socket.IO-sessions. I'll leave my old post below for historical purposes:
I got this work quite neatly without having to bypass the flashsocket transport as per pr0zac's solution above. I am also using express with Socket.IO. Here's how.
First, pass the session ID to the view:
app.get('/', function(req,res){
res.render('index.ejs', {
locals: {
connect_sid: req.sessionID
// ...
}
});
});
Then in your view, link it in with Socket.IO client-side:
<script>
var sid = '<%= connect_sid %>';
var socket = new io.Socket();
socket.connect();
</script>
<input type="button" value="Ping" onclick="socket.send({sid:sid, msg:'ping'});"/>
Then in your server-side Socket.IO listener, pick it up and read/write the session data:
var socket = io.listen(app);
socket.on('connection', function(client){
client.on('message', function(message){
session_store.get(message.sid, function(error, session){
session.pings = session.pings + 1 || 1;
client.send("You have made " + session.pings + " pings.");
session_store.set(message.sid, session); // Save the session
});
});
});
In my case, my session_store
is Redis, using the redis-connect
library.
var RedisStore = require('connect-redis');
var session_store = new RedisStore;
// ...
app.use(express.session({ store: session_store }));
Hope this helps someone who finds this post while searching Google (as I did ;)
See this: Socket.IO Authentication
I would suggest not fetching anything via client.request...
or client.listener...
as that is not directly attached to the client
object and always point to the last logged in user!
For future readers - There is an elegant and easy way to access the session inside socket.io with express-session. From socket.io documentation:
Most existing Express middleware modules should be compatible with Socket.IO, you just need a little wrapper function to make the method signatures match:
const wrap = middleware => (socket, next) => middleware(socket.request, {}, next);
The middleware functions that end the request-response cycle and do not call next() will not work though.
Example with express-session:
const session = require("express-session");
io.use(wrap(session({ secret: "cats" })));
io.on("connection", (socket) => {
const session = socket.request.session; // here you get access to the session :)
});
Check out Socket.IO-connect
Connect WebSocket Middleware Wrapper Around Socket.IO-node https://github.com/bnoguchi/Socket.IO-connect
This will allow you to push the Socket.IO request(s) down the Express/Connect middleware stack before handling it with Socket.IO event handlers, giving you access to the session, cookies, and more. Although, I'm not sure that it works with all of Socket.IO's transports.
I am not sure that I am doing it right. https://github.com/LearnBoost/socket.io/wiki/Authorizing
With the handshake data, you can access to the cookies. And in the cookies, you can grab connect.sid which is the session id for each client. And then use the connect.sid to get the session data from database (I am assuming you are using RedisStore)
You can make use of express-socket.io-session .
Share a cookie-based express-session middleware with socket.io. Works with express > 4.0.0 and socket.io > 1.0.0 and won't be backward compatible.
Worked for me!!
As of February 2022 this is supported by Socket.IO v4:
https://socket.io/docs/v4/faq/#usage-with-express-session
const express = require('express');
const session = require('express-session');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
const sessionMiddleware = session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }});
// register middleware in Express
app.use(sessionMiddleware);
// register middleware in Socket.IO
io.use((socket, next) => {
sessionMiddleware(socket.request, {}, next);
// sessionMiddleware(socket.request, socket.request.res, next); will not work with websocket-only
// connections, as 'socket.request.res' will be undefined in that case
});
io.on('connection', (socket) => {
const session = socket.request.session;
session.connections++;
session.save();
});
const port = process.env.PORT || 3000;
server.listen(port, () => console.log('server listening on port ' + port));
You can have a look at this: https://github.com/bmeck/session-web-sockets
or alternatively you can use:
io.on('connection', function(client) {
var session = client.listener.server.viewHelpers;
// use session here
});
Hope this helps.
精彩评论