Come condividere sessioni con Socket.IO 1.xe Express 4.x?

Come posso condividere una sessione con Socket.io 1.0 e Express 4.x? Io uso un negozio Redis, ma credo che non dovrebbe essere importante. So che devo usare un middleware per guardare i cookie e recuperare la sessione, ma non so come. Ho cercato ma non ho trovato nessun lavoro

var RedisStore = connectRedis(expressSession); var session = expressSession({ store: new RedisStore({ client: redisClient }), secret: mysecret, saveUninitialized: true, resave: true }); app.use(session); io.use(function(socket, next) { var handshake = socket.handshake; if (handshake.headers.cookie) { var str = handshake.headers.cookie; next(); } else { next(new Error('Missing Cookies')); } }); 

Solutions Collecting From Web of "Come condividere sessioni con Socket.IO 1.xe Express 4.x?"

La soluzione è sorprendentemente semplice. Non è molto ben documentato. È ansible utilizzare il middleware di sessione express anche come middleware Socket.IO con un piccolo adattatore come questo:

 sio.use(function(socket, next) { sessionMiddleware(socket.request, socket.request.res, next); }); 

Ecco un esempio completo con Express 4.x, Socket.IO 1.x e Redis:

 var express = require("express"); var Server = require("http").Server; var session = require("express-session"); var RedisStore = require("connect-redis")(session); var app = express(); var server = Server(app); var sio = require("socket.io")(server); var sessionMiddleware = session({ store: new RedisStore({}), // XXX redis server config secret: "keyboard cat", }); sio.use(function(socket, next) { sessionMiddleware(socket.request, socket.request.res, next); }); app.use(sessionMiddleware); app.get("/", function(req, res){ req.session // Session object in a normal request }); sio.sockets.on("connection", function(socket) { socket.request.session // Now it's available from Socket.IO sockets too! Win! }); server.listen(8080); 

Solo un mese e mezzo fa ho affrontato lo stesso problema e in seguito ho scritto un ampio post sul blog su questo argomento che va insieme a un’app demo completamente funzionante ospitata su GitHub. La soluzione si basa su moduli Express-session , cookie-parser e connect-redis node per bind tutto. Ti consente di accedere e modificare sessioni dal contesto REST e Sockets che è abbastanza utile.

Le due parti cruciali sono la configurazione del middleware:

 app.use(cookieParser(config.sessionSecret)); app.use(session({ store: redisStore, key: config.sessionCookieKey, secret: config.sessionSecret, resave: true, saveUninitialized: true })); 

… e configurazione del server SocketIO:

 ioServer.use(function (socket, next) { var parseCookie = cookieParser(config.sessionSecret); var handshake = socket.request; parseCookie(handshake, null, function (err, data) { sessionService.get(handshake, function (err, session) { if (err) next(new Error(err.message)); if (!session) next(new Error("Not authorized")); handshake.session = session; next(); }); }); }); 

Vanno insieme a un semplice modulo sessionService che ho creato, che ti permette di fare alcune operazioni di base con le sessioni e che il codice assomiglia a questo:

 var config = require('../config'); var redisClient = null; var redisStore = null; var self = module.exports = { initializeRedis: function (client, store) { redisClient = client; redisStore = store; }, getSessionId: function (handshake) { return handshake.signedCookies[config.sessionCookieKey]; }, get: function (handshake, callback) { var sessionId = self.getSessionId(handshake); self.getSessionBySessionID(sessionId, function (err, session) { if (err) callback(err); if (callback != undefined) callback(null, session); }); }, getSessionBySessionID: function (sessionId, callback) { redisStore.load(sessionId, function (err, session) { if (err) callback(err); if (callback != undefined) callback(null, session); }); }, getUserName: function (handshake, callback) { self.get(handshake, function (err, session) { if (err) callback(err); if (session) callback(null, session.userName); else callback(null); }); }, updateSession: function (session, callback) { try { session.reload(function () { session.touch().save(); callback(null, session); }); } catch (err) { callback(err); } }, setSessionProperty: function (session, propertyName, propertyValue, callback) { session[propertyName] = propertyValue; self.updateSession(session, callback); } }; 

Dato che c’è più codice per tutto questo (come inizializzare i moduli, lavorare con socket e chiamate REST sia sul lato client che sul lato server), non incollerò tutto il codice qui, puoi vederlo sul GitHub e puoi fare tutto ciò che vuoi con esso.

esprimere-socket.io-session

è una soluzione pronta per il tuo problema. Normalmente la sessione creata su socket.io end ha un sid diverso da quelli creati in express.js

Prima di conoscere questo fatto, quando stavo lavorando per trovare la soluzione, ho trovato qualcosa di strano. Le sessioni create dall’istanza express.js erano accessibili alla fine socket.io, ma non era ansible la stessa cosa per il contrario. E presto sono venuto a sapere che devo lavorare a mio modo gestendo sid per risolvere quel problema. Ma, c’era già un pacchetto scritto per affrontare questo problema. È ben documentato e porta a termine il lavoro. Spero che sia d’aiuto

Usando la risposta di Bradley Lederholz, è così che l’ho fatto funzionare per me stesso. Si prega di fare riferimento alla risposta di Bradley Lederholz, per ulteriori spiegazioni.

 var app = express(); var server = require('http').createServer(app); var io = require('socket.io'); var cookieParse = require('cookie-parser')(); var passport = require('passport'); var passportInit = passport.initialize(); var passportSession = passport.session(); var session = require('express-session'); var mongoStore = require('connect-mongo')(session); var mongoose = require('mongoose'); var sessionMiddleware = session({ secret: 'some secret', key: 'express.sid', resave: true, httpOnly: true, secure: true, ephemeral: true, saveUninitialized: true, cookie: {}, store:new mongoStore({ mongooseConnection: mongoose.connection, db: 'mydb' }); }); app.use(sessionMiddleware); io = io(server); io.use(function(socket, next){ socket.client.request.originalUrl = socket.client.request.url; cookieParse(socket.client.request, socket.client.request.res, next); }); io.use(function(socket, next){ socket.client.request.originalUrl = socket.client.request.url; sessionMiddleware(socket.client.request, socket.client.request.res, next); }); io.use(function(socket, next){ passportInit(socket.client.request, socket.client.request.res, next); }); io.use(function(socket, next){ passportSession(socket.client.request, socket.client.request.res, next); }); io.on('connection', function(socket){ ... }); ... server.listen(8000); 

L’ho risolto, ma non è perfetto. Non supporta i cookie firmati, ecc. Ho usato la funzione getcookie di express-session . La funzione modificata è la seguente:

  io.use(function(socket, next) { var cookie = require("cookie"); var signature = require('cookie-signature'); var debug = function() {}; var deprecate = function() {}; function getcookie(req, name, secret) { var header = req.headers.cookie; var raw; var val; // read from cookie header if (header) { var cookies = cookie.parse(header); raw = cookies[name]; if (raw) { if (raw.substr(0, 2) === 's:') { val = signature.unsign(raw.slice(2), secret); if (val === false) { debug('cookie signature invalid'); val = undefined; } } else { debug('cookie unsigned') } } } // back-compat read from cookieParser() signedCookies data if (!val && req.signedCookies) { val = req.signedCookies[name]; if (val) { deprecate('cookie should be available in req.headers.cookie'); } } // back-compat read from cookieParser() cookies data if (!val && req.cookies) { raw = req.cookies[name]; if (raw) { if (raw.substr(0, 2) === 's:') { val = signature.unsign(raw.slice(2), secret); if (val) { deprecate('cookie should be available in req.headers.cookie'); } if (val === false) { debug('cookie signature invalid'); val = undefined; } } else { debug('cookie unsigned') } } } return val; } var handshake = socket.handshake; if (handshake.headers.cookie) { var req = {}; req.headers = {}; req.headers.cookie = handshake.headers.cookie; var sessionId = getcookie(req, "connect.sid", mysecret); console.log(sessionId); myStore.get(sessionId, function(err, sess) { console.log(err); console.log(sess); if (!sess) { next(new Error("No session")); } else { console.log(sess); socket.session = sess; next(); } }); } else { next(new Error("Not even a cookie found")); } }); // Session backend config var RedisStore = connectRedis(expressSession); var myStore = new RedisStore({ client: redisClient }); var session = expressSession({ store: myStore, secret: mysecret, saveUninitialized: true, resave: true }); app.use(session); 

Ora, la risposta originale accettata non funziona neanche per me. Come @ Rahil051, ho usato il modulo express-socket.io-session e funziona ancora. Questo modulo utilizza cookie-parser, per analizzare l’ID di sessione prima di entrare nel middleware di sessione espressa. Penso che sia silmiar a @pootzko, @Mustafa e la risposta di @ Kosar.

Sto usando questi moduli:

 "dependencies": { "debug": "^2.6.1", "express": "^4.14.1", "express-session": "^1.15.1", "express-socket.io-session": "^1.3.2 "socket.io": "^1.7.3" } 

controlla i dati in socket.handshake:

 const debug = require('debug')('ws'); const sharedsession = require('express-socket.io-session'); module.exports = (server, session) => { const io = require('socket.io').listen(server); let connections = []; io.use(sharedsession(session, { autoSave: true, })); io.use(function (socket, next) { debug('check handshake %s', JSON.stringify(socket.handshake, null, 2)); debug('check headers %s', JSON.stringify(socket.request.headers)); debug('check socket.id %s', JSON.stringify(socket.id)); next(); }); io.sockets.on('connection', (socket) => { connections.push(socket); }); };