socket.io e session?


96

Sto usando Express Framework. Voglio raggiungere i dati della sessione da socket.io. Ho provato express dynamicHelpers con i dati client.listener.server.dynamicViewHelpers, ma non riesco a ottenere i dati della sessione. C'è un modo semplice per fare questo? Si prega di consultare il codice

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
    }); 
});

5
Oppure puoi usare questo post MOLTO BELLO: danielbaulig.de/socket-ioexpress
Fabiano Soriani

3
@FabianoPS - non funzionerà più - connect non fornisce più il metodo parseCookie su cui si basa.
UpTheCreek

1
@UpTheCreek - Dal momento che connect non utilizza più il metodo parseCookie, come può essere possibile?
Agosto

@Aust - Bella domanda, non so quale sia l'approccio migliore ora. Questo è davvero un casino IMO. In modo fastidioso, la maggior parte delle discussioni sulle soluzioni alternative si concentra anche su socket.io (non tutti usano socket.io!). C'è una funzione parseSignedCookie ora, ma anche quella privata, quindi è anche a rischio di interrompere le modifiche.
UpTheCreek

2
Per le versioni più recenti di Socket.IO (1.x) ed Express (4.x) controllare questa domanda SO: stackoverflow.com/questions/25532692/...
pootzko

Risposte:


68

Questo non funzionerà per i socket che attraversano il trasporto flashsocket (non invia al server i cookie necessari) ma funziona in modo affidabile per tutto il resto. Ho solo disabilitato il trasporto flashsocket nel mio codice.

Per farlo funzionare, nel lato express / connect, definisco esplicitamente il session store in modo da poterlo utilizzare all'interno di socket:

MemoryStore = require('connect/middleware/session/memory'),
var session_store = new MemoryStore();
app.configure(function () {
  app.use(express.session({ store: session_store }));
});

Quindi all'interno del mio codice socket, includo il framework connect in modo da poter utilizzare il suo cookie parsing per recuperare il connect.sid dai cookie. Quindi cerco la sessione nel session store che ha quel connect.sid in questo modo:

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!!!!
    });
  }
});

È quindi possibile utilizzare la sessione secondo necessità.


3
Sembra che socket_client.request sia stato rimosso nelle ultime versioni di socket.io-node
Art

6
Attenzione ... ci sono nuove convenzioni per farlo ora ... Suggerirei di utilizzare invece l'autenticazione Socket.IO. Vedi il post di @Jeffer
BMiner

2
Sfortunatamente questo non funzionerà più - parseCookie non fa più parte di connect utils. Apparentemente non è mai stato parte dell'API pubblica. C'è un'alternativa disordinata: parseSignedCookie, ma anche questo è privato, quindi immagino che rischi di scomparire anche lui ..
UpTheCreek

Ora che ci sto pensando ... perché non impostare l'archivio per i biscotti e l'archivio per il socket nello stesso negozio?
James

34

La soluzione del modulo Socket.IO-sessions espone l'app agli attacchi XSS esponendo l'ID sessione a livello di client (scripting).

Controlla invece questa soluzione (per Socket.IO> = v0.7). Vedi i documenti qui .


1
@ Jeffer - quella seconda soluzione non funzionerà più con la versione corrente di connect.
UpTheCreek

2
-1 socket.ioè ciò che sta esponendo l'ID di sessione, non quel modulo. Questo non è un grosso problema dato che l'ID di sessione è comunque memorizzato sul lato client in un cookie ... Inoltre, quel tutorial non funziona per l'ultima versione di Express.
Aust

1
il link della tua soluzione reindirizza semplicemente alla socket.iopagina github ..?
TJ

8

Suggerisco di non reinventare completamente la ruota. Lo strumento di cui hai bisogno è già un pacchetto npm, penso che questo sia ciò di cui hai bisogno: session.socket.io Lo sto usando in questi giorni e sarà molto utile immagino !! Collegare la sessione express al livello socket.io avrà così tanti vantaggi!


6
Ecco un modulo aggiornato che supporta socket.io-express-sessions per socket.io> = 1.0 github.com/xpepermint/socket.io-express-session
blnc

4

Modifica: dopo aver provato alcuni moduli che non funzionavano, in realtà sono andato e ho scritto la mia libreria per farlo. Spina senza vergogna: dai un'occhiata a https://github.com/aviddiviner/Socket.IO-sessions . Lascio il mio vecchio post qui sotto per scopi storici:


Ho ottenuto questo lavoro abbastanza ordinatamente senza dover bypassare il trasporto flashsocket come per la soluzione di pr0zac sopra. Sto anche usando express con Socket.IO. Ecco come.

Innanzitutto, passa l'ID della sessione alla vista:

app.get('/', function(req,res){
  res.render('index.ejs', {
    locals: { 
      connect_sid: req.sessionID
      // ...
    }
  });
});

Quindi, a tuo avviso, collegalo con Socket.IO lato client:

<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'});"/>

Quindi nel tuo listener Socket.IO lato server, raccoglilo e leggi / scrivi i dati della sessione:

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
    });
  });
});

Nel mio caso, il mio session_storeè Redis, utilizzando la redis-connectlibreria.

var RedisStore = require('connect-redis');
var session_store = new RedisStore;
// ...
app.use(express.session({ store: session_store }));

Spero che questo aiuti qualcuno che trova questo post durante la ricerca su Google (come ho fatto io;)


8
Mettere l'ID di sessione nell'html del client non è una buona idea dal punto di vista della sicurezza ...
UpTheCreek

4
Perché inserire l'ID di sessione nell'HTML è una cattiva idea quando l'ID di sessione è già memorizzato in un cookie locale?
Gavin

3
Perché i cookie non sono accessibili da javascript quando impostati come cookie HttpOnly. Inserendo session.sid nell'HTML si fornisce all'attaccante tutto ciò di cui ha bisogno nel DOM.
rochal

3

Vedi questo: Autenticazione Socket.IO

Suggerirei di non recuperare nulla tramite client.request...o client.listener...poiché non è direttamente collegato clientall'oggetto e punta sempre all'ultimo utente connesso!


2

Dai un'occhiata a Socket.IO-connect

Connect WebSocket Middleware Wrapper Around Socket.IO-node https://github.com/bnoguchi/Socket.IO-connect

Ciò ti consentirà di eseguire il push delle richieste Socket.IO nello stack middleware Express / Connect prima di gestirle con i gestori di eventi Socket.IO, dandoti accesso alla sessione, ai cookie e altro. Tuttavia, non sono sicuro che funzioni con tutti i trasporti di Socket.IO.


sfortunatamente quel modulo sta ancora usando la v0.6 di socket.io
fent

2

Puoi utilizzare express-socket.io-session .

Condividi un middleware di sessione express basato su cookie con socket.io. Funziona con express> 4.0.0 e socket.io> 1.0.0 e non sarà compatibile con le versioni precedenti.

Ha funzionato per me !!


Hey. Come useresti i valori di sessione nel front-end? Non riesco a vederli nei documenti npm.
Hari Ram

1

Puoi dare un'occhiata a questo: https://github.com/bmeck/session-web-sockets

oppure in alternativa puoi usare:

io.on('connection', function(client) { 
  var session = client.listener.server.viewHelpers; 
  // use session here 
});

Spero che questo ti aiuti.


Conosco session-web-socket ma non voglio usare una libreria per questo, sto cercando una soluzione semplice. Ho provato client.listener.server.viewHelpers; ma ha restituito questo: {}
sfs

2
anche se all'inizio sembra funzionare, porta a condizioni di gara. Ti suggerisco di evitarlo completamente.
Shripad Krishna

1

Non sono sicuro di farlo bene. https://github.com/LearnBoost/socket.io/wiki/Authorizing

Con i dati dell'handshake è possibile accedere ai cookie. E nei cookie, puoi prendere connect.sid che è l'id di sessione per ogni client. Quindi usa connect.sid per ottenere i dati della sessione dal database (presumo che tu stia usando RedisStore)


questa è esattamente la strada da percorrere, ma non sei cool, quindi non puoi ottenere punti di overflow dello stack. github.com/tcr/socket.io-session e github.com/functioncallback/session.socket.io Mi piace il primo un po 'meglio è più pulito. Il secondo è un po 'meglio documentato.
James

@TJ Mi dispiace ma ti rendi conto che la risposta è stata 2 anni fa? E probabilmente ora non funzionerebbe
Tan Nguyen

@TanNguyen Lo so, ecco perché ti ho notificato in modo che tu possa aggiornare la risposta necessariamente piuttosto che indirizzare le persone a link morti
TJ

@TJ Grazie per questo. Sfortunatamente, 2 anni fa mi sono allontanato da socket.io a causa di problemi di prestazioni. Pertanto, non so quale sia il modo attuale di gestire la sessione in socket.io
Tan Nguyen
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.