socket.io und session?

95

Ich benutze Express Framework. Ich möchte Sitzungsdaten von socket.io erreichen. Ich habe versucht, dynamicHelpers mit client.listener.server.dynamicViewHelpers-Daten auszudrücken, aber ich kann keine Sitzungsdaten abrufen. Gibt es eine einfache Möglichkeit, dies zu tun? Bitte beachten Sie den 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
    }); 
});
sfs
quelle
5
Oder verwenden Sie diesen SEHR SCHÖNEN
Fabiano Soriani
3
@FabianoPS - funktioniert nicht mehr - connect bietet nicht mehr die parseCookie-Methode, auf die sich dies stützt.
UpTheCreek
1
@UpTheCreek - Wie kann dies möglich sein, da connect die parseCookie-Methode nicht mehr verwendet?
Aust
@Aust - Gute Frage, ich weiß nicht, was der beste Ansatz jetzt ist. Das ist wirklich ein Chaos IMO. Ärgerlicherweise konzentrieren sich die meisten Workaround-Diskussionen auch auf socket.io (nicht jeder verwendet socket.io!). Es gibt jetzt eine parseSignedCookie-Funktion, aber diese ist auch privat, sodass das Risiko besteht, dass auch Änderungen vorgenommen werden.
UpTheCreek
2
Für neuere Versionen von Socket.IO (1.x) und Express (4.x) überprüfen Sie diese SO-Frage: stackoverflow.com/questions/25532692/…
pootzko

Antworten:

68

Dies funktioniert nicht für Sockets, die über den Flashsocket-Transport gehen (es sendet dem Server nicht die erforderlichen Cookies), aber es funktioniert zuverlässig für alles andere. Ich deaktiviere nur den Flashsocket-Transport in meinem Code.

Damit es funktioniert, definiere ich auf der Express / Connect-Seite explizit den Sitzungsspeicher, damit ich ihn im Socket verwenden kann:

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

Dann füge ich in meinen Socket-Code das Connect-Framework ein, damit ich mithilfe der Cookie-Analyse die connect.sid aus den Cookies abrufen kann. Ich schaue dann die Sitzung im Sitzungsspeicher nach, der diese connect.sid hat:

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

Sie können die Sitzung dann nach Bedarf verwenden.

pr0zac
quelle
3
Es sieht so aus, als ob socket_client.request in den neuesten Versionen von socket.io-node entfernt wurde
Art
6
Achtung ... es gibt jetzt neue Konventionen dafür ... Ich würde vorschlagen, stattdessen die Socket.IO-Authentifizierung zu verwenden. Siehe Beitrag von @Jeffer
BMiner
2
Leider funktioniert dies nicht mehr - parseCookie ist nicht mehr Teil von connect utils. Anscheinend war es nie Teil der öffentlichen API. Es gibt eine unordentliche Alternative - parseSignedCookie, aber diese ist auch privat, daher besteht die Gefahr, dass sie auch verschwindet.
UpTheCreek
Jetzt, wo ich darüber nachdenke, warum nicht einfach den Speicher für die Cookies und den Speicher für den Socket auf denselben Speicher einstellen?
James
34

Die Socket.IO-Sessions-Modullösung setzt die App XSS-Angriffen aus, indem die Sitzungs-ID auf Client-Ebene (Skripterstellung) verfügbar gemacht wird.

Überprüfen Sie stattdessen diese Lösung (für Socket.IO> = v0.7). Siehe Dokumente hier .

Jeffer
quelle
1
@ Jeffer - diese zweite Lösung funktioniert mit der aktuellen Version von Connect nicht mehr.
UpTheCreek
2
-1 socket.ioist das, was die Sitzungs-ID verfügbar macht, nicht dieses Modul. Dies ist keine große Sache, da die Sitzungs-ID sowieso clientseitig in einem Cookie gespeichert wird ... Auch dieses Tutorial funktioniert nicht für die neueste Version von Express.
Aust
1
Ihr socket.ioLösungslink leitet einfach zur Github-Seite weiter.
TJ
8

Ich schlage vor, das Rad nicht komplett neu zu erfinden. Die Tools, die Sie benötigen, sind bereits ein npm-Paket. Ich denke, das ist, was Sie brauchen: session.socket.io Ich benutze es in diesen Tagen und es wird sehr hilfreich sein, denke ich !! Das Verknüpfen der Express-Sitzung mit der socket.io-Ebene hat so viele Vorteile!

Francesco
quelle
6
Hier ist ein aktualisiertes Modul , das unterstützt Socket.io-Express-Sitzungen für socket.io> = 1,0 github.com/xpepermint/socket.io-express-session
BLNC
4

Bearbeiten: Nachdem ich einige Module ausprobiert habe, die nicht funktionierten, habe ich tatsächlich meine eigene Bibliothek geschrieben, um dies zu tun. Schamloser Stecker: Schauen Sie unter https://github.com/aviddiviner/Socket.IO-sessions nach . Ich werde meinen alten Beitrag unten aus historischen Gründen verlassen:


Ich habe diese Arbeit ganz ordentlich bekommen, ohne den Flashsocket- Transport gemäß der obigen Lösung von pr0zac umgehen zu müssen . Ich benutze auch Express mit Socket.IO. Hier ist wie.

Übergeben Sie zunächst die Sitzungs-ID an die Ansicht:

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

Verknüpfen Sie es dann Ihrer Ansicht nach mit Socket.IO clientseitig:

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

Nehmen Sie es dann in Ihrem serverseitigen Socket.IO-Listener auf und lesen / schreiben Sie die Sitzungsdaten:

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 meinem Fall ist mein session_storeRedis, der die redis-connectBibliothek benutzt.

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

Hoffe, das hilft jemandem, der diesen Beitrag bei der Suche in Google findet (wie ich;)

Dave
quelle
8
Das Einfügen Ihrer Sitzungs-ID in das Client-HTML ist aus Sicherheitsgründen keine gute Idee ...
UpTheCreek
4
Warum ist das Einfügen der Sitzungs-ID in den HTML-Code eine so schlechte Idee, wenn die Sitzungs-ID bereits in einem lokalen Cookie gespeichert ist?
Gavin
3
Weil auf Cookies nicht über Javascript zugegriffen werden kann, wenn sie als HttpOnly-Cookie festgelegt sind. Indem Sie session.sid in den HTML-Code einfügen, geben Sie dem Angreifer alles, was er im DOM benötigt.
Rochal
3

Sieh dir das an: Socket.IO-Authentifizierung

Ich würde vorschlagen, nichts über client.request...oder abzurufen, client.listener...da dies nicht direkt mit dem clientObjekt verbunden ist und immer auf den zuletzt angemeldeten Benutzer verweist!

Shripad Krishna
quelle
2

Auschecken Socket.IO-connect an

Verbinden Sie den WebSocket Middleware Wrapper mit dem Socket.IO-Knoten https://github.com/bnoguchi/Socket.IO-connect

Auf diese Weise können Sie die Socket.IO-Anforderung (en) in den Express / Connect-Middleware-Stack verschieben, bevor Sie sie mit Socket.IO-Ereignishandlern bearbeiten, um auf die Sitzung, Cookies und mehr zuzugreifen. Ich bin mir jedoch nicht sicher, ob es mit allen Transporten von Socket.IO funktioniert.

BMiner
quelle
Leider verwendet dieses Modul immer noch v0.6 von socket.io
fent
2

Sie können express-socket.io-session verwenden .

Teilen Sie eine Cookie-basierte Express-Session-Middleware mit socket.io. Funktioniert mit Express> 4.0.0 und socket.io> 1.0.0 und ist nicht abwärtskompatibel.

Hat für mich gearbeitet !!

nonybrighto
quelle
Hallo. Wie würden Sie die Sitzungswerte im Frontend verwenden? Ich kann sie in npm-Dokumenten nicht sehen.
Hari Ram
1

Sie können dies überprüfen : https://github.com/bmeck/session-web-sockets

oder alternativ können Sie verwenden:

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

Hoffe das hilft.

Intellidiot
quelle
Ich kenne Session-Web-Sockets, aber ich möchte keine Bibliothek dafür verwenden, ich suche nach einer einfachen Lösung. Ich habe versucht, client.listener.server.viewHelpers; aber es gab dies zurück: {}
sfs
2
Obwohl dies zunächst zu funktionieren scheint, führt es zu Rennbedingungen. Ich schlage vor, Sie vermeiden es vollständig.
Shripad Krishna
1

Ich bin mir nicht sicher, ob ich es richtig mache. https://github.com/LearnBoost/socket.io/wiki/Authorizing

Mit den Handshake-Daten können Sie auf die Cookies zugreifen. Und in den Cookies können Sie connect.sid abrufen, die die Sitzungs-ID für jeden Client ist. Verwenden Sie dann die Datei connect.sid, um die Sitzungsdaten aus der Datenbank abzurufen (ich gehe davon aus, dass Sie RedisStore verwenden).

Tan Nguyen
quelle
Dies ist genau der richtige Weg, aber Sie sind nicht cool, sodass Sie keine Stapelüberlaufpunkte erhalten können. github.com/tcr/socket.io-session und github.com/functioncallback/session.socket.io Ich mag das erste etwas besser, es ist sauberer. Der zweite ist etwas besser dokumentiert.
James
@TJ Das tut mir leid, aber ist dir klar, dass die Antwort vor 2 Jahren war? Und es würde jetzt wahrscheinlich nicht funktionieren
Tan Nguyen
@ TanNguyen Ich weiß, deshalb habe ich Sie benachrichtigt, damit Sie die Antwort unbedingt aktualisieren können, als Menschen auf tote Links zu verweisen
TJ
@TJ Danke dafür. Leider bin ich vor 2 Jahren wegen eines Leistungsproblems von socket.io weggezogen. Daher weiß ich nicht, wie die Sitzung derzeit in socket.io
Tan Nguyen