socket.io i sesja?

96

Używam Express Framework. Chcę uzyskać dostęp do danych sesji z socket.io. Próbowałem wyrazić dynamicHelpers z danymi client.listener.server.dynamicViewHelpers, ale nie mogę uzyskać danych sesji. Czy jest na to prosty sposób? Proszę zobaczyć kod

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
źródło
5
Lub skorzystaj z tego BARDZO MIŁEGO
Fabiano Soriani
3
@FabianoPS - już nie będzie działać - connect nie zapewnia już metody parseCookie, na której to polega.
UpTheCreek
1
@UpTheCreek - Skoro connect nie używa już metody parseCookie, jak to możliwe?
Sierpień,
@Aust - Dobre pytanie, nie wiem, jakie jest teraz najlepsze podejście. To naprawdę bałagan IMO. Irytująco większość dyskusji na temat obejść jest również skupiona na socket.io (nie wszyscy używają socket.io!). Istnieje teraz funkcja parseSignedCookie, ale jest ona również prywatna, więc istnieje również ryzyko zerwania zmian.
UpTheCreek
2
W przypadku nowszych wersji Socket.IO (1.x) i Express (4.x) sprawdź to pytanie SO: stackoverflow.com/questions/25532692/ ...
pootzko

Odpowiedzi:

68

To nie zadziała dla gniazd przechodzących przez transport flashsocket (nie wysyła do serwera potrzebnych plików cookie), ale działa niezawodnie w przypadku wszystkiego innego. Po prostu wyłączam transport flashsocket w moim kodzie.

Aby to zadziałało, po stronie express / connect wyraźnie definiuję magazyn sesji, aby móc go używać w gnieździe:

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

Następnie w kodzie gniazda dołączam strukturę connect, dzięki czemu mogę użyć analizy plików cookie w celu pobrania connect.sid z plików cookie. Następnie wyszukuję sesję w magazynie sesji, który ma to connect.sid w następujący sposób:

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

Następnie możesz korzystać z sesji w razie potrzeby.

pr0zac
źródło
3
Wygląda na to, że socket_client.request został usunięty w najnowszych wersjach socket.io-node
Art.
6
Uwaga ... są teraz nowe konwencje ... Zamiast tego sugerowałbym użycie uwierzytelniania Socket.IO. Zobacz post z @Jeffer
BMiner
2
Niestety to już nie zadziała - parseCookie nie jest już częścią narzędzi connect. Najwyraźniej nigdy nie był częścią publicznego interfejsu API. Istnieje alternatywa brudny - parseSignedCookie, ale to jest również prywatny, więc myślę, że ITS zagrożonych zniknięciem zbyt ..
UpTheCreek
Teraz, kiedy o tym myślę… dlaczego nie ustawić sklepu dla plików cookie i sklepu dla gniazda na ten sam sklep?
James
34

Rozwiązanie modułu Socket.IO-session naraża aplikację na ataki XSS, ujawniając identyfikator sesji na poziomie klienta (skryptów).

Zamiast tego sprawdź to rozwiązanie (dla Socket.IO> = v0.7). Zobacz dokumentację tutaj .

Jeffer
źródło
1
@Jeffer - to drugie rozwiązanie nie będzie już działać z obecną wersją connect.
UpTheCreek
2
-1 socket.iojest tym, co ujawnia identyfikator sesji, a nie ten moduł. Nie jest to wielka sprawa, ponieważ identyfikator sesji i tak jest przechowywany po stronie klienta w pliku cookie ... Również ten samouczek nie działa w najnowszej wersji Express.
Sierpień
1
Twój link do rozwiązania po prostu przekierowuje do socket.iostrony github ..?
TJ
8

Proponuję nie wymyślać całkowicie koła na nowo. Narzędzia, których potrzebujesz, to już pakiet npm. Myślę, że właśnie tego potrzebujesz: session.socket.io Używam go w tych dniach i myślę, że będzie bardzo pomocny !! Połączenie sesji ekspresowej z warstwą socket.io będzie miało wiele zalet!

Francesco
źródło
6
Oto zaktualizowany moduł obsługujący sesje socket.io-express-session dla socket.io> = 1.0 github.com/xpepermint/socket.io-express-session
blnc
4

Edycja: Po wypróbowaniu niektórych modułów, które nie działały, napisałem własną bibliotekę, aby to zrobić. Bezwstydna wtyczka: sprawdź to na https://github.com/aviddiviner/Socket.IO-sessions . Zostawię mój stary post poniżej w celach historycznych:


Otrzymałem tę pracę całkiem dobrze, bez konieczności omijania transportu flashsocket, jak w rozwiązaniu pr0zac powyżej. Używam również Express z Socket.IO. Oto jak.

Najpierw przekaż identyfikator sesji do widoku:

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

Następnie w swoim widoku połącz go ze stroną klienta Socket.IO:

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

Następnie w odbiorniku Socket.IO po stronie serwera, podnieś go i przeczytaj / zapisz dane sesji:

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

W moim przypadku mój session_storeto Redis, korzystając z redis-connectbiblioteki.

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

Mam nadzieję, że pomoże to komuś, kto znajdzie ten post podczas wyszukiwania w Google (tak jak ja;)

Dave
źródło
8
Umieszczenie identyfikatora sesji w html klienta nie jest dobrym pomysłem z punktu widzenia bezpieczeństwa ...
UpTheCreek
4
Dlaczego umieszczenie identyfikatora sesji w kodzie HTML jest tak złym pomysłem, skoro identyfikator sesji jest już przechowywany w lokalnym pliku cookie?
Gavin,
3
Ponieważ nie można uzyskać dostępu do plików cookie z javascript, gdy są ustawione jako plik cookie HttpOnly. Umieszczając session.sid w kodzie HTML, dajesz atakującemu wszystko, czego potrzebuje w DOM.
rochal
3

Zobacz to: Uwierzytelnianie Socket.IO

Sugerowałbym, aby nie pobierać niczego za pośrednictwem client.request...lub, client.listener...ponieważ nie jest to bezpośrednio dołączone do clientobiektu i zawsze wskazuje na ostatnio zalogowanego użytkownika!

Shripad Krishna
źródło
2

Sprawdź Socket.IO-connect

Połącz WebSocket Middleware Wrapper Around Socket.IO-node https://github.com/bnoguchi/Socket.IO-connect

Pozwoli to na wypchnięcie żądań Socket.IO w dół stosu oprogramowania pośredniego Express / Connect przed obsłużeniem go za pomocą programów obsługi zdarzeń Socket.IO, zapewniając dostęp do sesji, plików cookie i nie tylko. Chociaż nie jestem pewien, czy działa to ze wszystkimi transportami Socket.IO.

BMiner
źródło
niestety ten moduł nadal używa wersji 0.6 z socket.io
fent
2

Możesz skorzystać z express-socket.io-session .

Udostępnij oprogramowanie pośredniczące sesji ekspresowej opartej na plikach cookie z socket.io. Działa z express> 4.0.0 i socket.io> 1.0.0 i nie będzie kompatybilny wstecz.

Pracował dla mnie !!

nonybrighto
źródło
Hej. Jak użyłbyś wartości sesji w interfejsie użytkownika? Nie widzę ich w dokumentach npm.
Hari Ram
1

Możesz rzucić okiem na to: https://github.com/bmeck/session-web-sockets

lub alternatywnie możesz użyć:

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

Mam nadzieję że to pomoże.

intellidiot
źródło
Znam gniazda sieciowe sesji, ale nie chcę do tego używać biblioteki, szukam prostego rozwiązania. Próbowałem client.listener.server.viewHelpers; ale zwróciło to: {}
sfs
2
chociaż wydaje się to działać na początku, prowadzi to do warunków wyścigowych. Proponuję całkowicie tego unikać.
Shripad Krishna
1

Nie jestem pewien, czy robię to dobrze. https://github.com/LearnBoost/socket.io/wiki/Authorizing

Dane dotyczące uzgadniania umożliwiają dostęp do plików cookie. W plikach cookie możesz pobrać connect.sid, który jest identyfikatorem sesji dla każdego klienta. A następnie użyj connect.sid, aby pobrać dane sesji z bazy danych (zakładam, że używasz RedisStore)

Tan Nguyen
źródło
to jest dokładnie droga, ale nie jesteś fajny, więc nie możesz uzyskać punktów przepełnienia stosu. github.com/tcr/socket.io-session i github.com/functioncallback/session.socket.io Pierwszy z nich podoba mi się trochę lepiej jego odkurzacz. Drugi jest nieco lepiej udokumentowany.
James,
@TJ Przepraszam, ale czy zdajesz sobie sprawę, że odpowiedź była 2 lata temu? I prawdopodobnie nie zadziała teraz
Tan Nguyen
@TanNguyen Wiem, dlatego powiadomiłem Cię, abyś koniecznie zaktualizował odpowiedź, niż wskazywał ludziom martwe linki
TJ
@TJ Dziękuję za to. Niestety odszedłem od socket.io ze względu na problem z wydajnością 2 lata temu. Dlatego nie wiem, jak obecnie radzę sobie z sesją w socket.io
Tan Nguyen