socket.io та сеанс?


95

Я використовую express framework. Я хочу отримати дані сеансу з socket.io. Я спробував Express ExpressHelpers з даними client.listener.server.dynamicViewHelpers, але я не можу отримати дані сеансу. Чи є простий спосіб це зробити? Перегляньте код

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
Або можете скористатися цим ДУЖЕ ПРИГОДНИМ дописом
Фабіано Соріані

3
@FabianoPS - більше не працюватиме - connect більше не надає метод parseCookie, на який це покладається.
UpTheCreek

1
@UpTheCreek - Оскільки connect вже не використовує метод parseCookie, як це можливо?
Австрія,

@Aust - Гарне запитання, я не знаю, який зараз найкращий підхід. Це справді безлад IMO. Прикро, що більшість обговорень щодо обхідних шляхів також зосереджуються на socket.io (не всі використовують socket.io!). Зараз є функція parseSignedCookie, але це теж приватно, тому вона також ризикує порушити зміни.
UpTheCreek,

2
Для більш нових версій Socket.io (1.x) і Express (4.x) перевірити це так питання: stackoverflow.com/questions/25532692 / ...
pootzko

Відповіді:


68

Це не буде працювати для сокетів, що переходять через транспорт flashsocket (він не надсилає серверу необхідні файли cookie), але надійно працює для всього іншого. Я просто відключаю транспорт flashsocket у своєму коді.

Щоб це працювало, на стороні express / connect я чітко визначаю сховище сеансів, щоб я міг використовувати його всередині сокета:

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

Потім всередині мого коду сокета я включаю фреймворк connect, щоб я міг використовувати його синтаксичний аналіз файлів cookie для отримання connect.sid із файлів cookie. Потім я шукаю сесію в сховищі сесій, в якій є connect.sid так:

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

Потім ви можете використовувати сеанс за потреби.


3
Схоже, socket_client.request було видалено в останніх версіях socket.io-node
Art

6
Обережно ... для цього зараз є нові правила ... Я б радив замість цього використовувати аутентифікацію Socket.IO. Переглянути допис від @Jeffer
BMiner

2
На жаль, це більше не працюватиме - parseCookie більше не є частиною підключення utils. Очевидно, це ніколи не було частиною публічного API. Існує безладна альтернатива - parseSignedCookie, але це також приватно, тому, мабуть, вона теж ризикує зникнути ..
UpTheCreek

Тепер, коли я думаю над цим ... чому б просто не встановити магазин для печива та магазин для розетки для того самого магазину?
Джеймс

34

Модульне рішення Socket.IO-сесій піддає програму атакам XSS, виставляючи ідентифікатор сеансу на рівні клієнта (сценарії).

Замість цього перевірте це рішення (для Socket.IO> = v0.7). Документи дивіться тут .


1
@Jeffer - це друге рішення більше не працюватиме з поточною версією connect.
UpTheCreek

2
-1 socket.io- це те, що виявляє ідентифікатор сеансу, а не той модуль. Це не велика справа, оскільки ідентифікатор сеансу в будь-якому випадку зберігається на стороні клієнта у файлі cookie ... Також цей підручник не працює для останньої версії Express.
Австрія

1
посилання на ваше рішення просто перенаправляє на socket.ioсторінку github ..?
TJ

8

Я пропоную не повністю винаходити колесо. Інструменти, які вам потрібні, це вже пакет npm. Я думаю, що це те, що вам потрібно: session.socket.io Я використовую його в наші дні, і це буде дуже корисно, я думаю !! Пов’язання експрес-сесії з шаром socket.io матиме стільки переваг!


6
Ось оновлений модуль, що підтримує socket.io-express-session для socket.io> = 1,0 github.com/xpepermint/socket.io-express-session
blnc

4

Редагувати: спробувавши деякі модулі, які не працювали, я фактично пішов і написав власну бібліотеку для цього. Безсоромна вилка: перевірте її на https://github.com/aviddiviner/Socket.IO-sessions . Я залишу свій старий пост нижче для історичних цілей:


Я виконав цю роботу досить акуратно, не маючи необхідності обходити транспорт flashsocket відповідно до рішення pr0zac вище. Я також використовую express із Socket.IO. Ось як.

Спочатку передайте ідентифікатор сеансу у подання:

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

Потім, на ваш погляд, зв’яжіть його з клієнтською стороною 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'});"/>

Потім у вашому серверному прослуховувачі Socket.IO підніміть його та прочитайте / запишіть дані сеансу:

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

У моєму випадку це мій session_storeРедіс, який користується redis-connectбібліотекою.

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

Сподіваюся, це допоможе тому, хто знайде цю публікацію під час пошуку в Google (як я це зробив;)


8
Внесення ідентифікатора сеансу в клієнтський html - це не гарна ідея з точки зору безпеки ...
UpTheCreek

4
Чому розміщення ідентифікатора сесії в HTML настільки погана ідея, коли ідентифікатор сесії вже зберігається в локальному файлі cookie?
Гевін

3
Оскільки до файлів cookie неможливо отримати доступ з JavaScript, якщо вони встановлені як файли cookie HttpOnly. Помістивши session.sid в HTML, ви надаєте зловмисникові все, що їм потрібно в DOM.
rochal

3

Дивіться це: Аутентифікація Socket.IO

Я б радив нічого не отримувати через client.request...або, client.listener...оскільки це не прив’язано безпосередньо до clientоб’єкта, і завжди вказувати на останнього зареєстрованого користувача!


2

Перевірте Socket.IO-connect

Підключіть WebSocket Middleware Wrapper навколо Socket.IO-вузол https://github.com/bnoguchi/Socket.IO-connect

Це дозволить вам просунути запити Socket.IO вниз по стеку проміжного програмного забезпечення Express / Connect перед тим, як обробляти їх із обробниками подій Socket.IO, надаючи вам доступ до сеансу, файлів cookie тощо. Хоча, я не впевнений, що це працює з усіма транспортами Socket.IO.


на жаль, цей модуль все ще використовує v0.6 socket.io
fent

2

Ви можете використовувати express-socket.io-session .

Поділіться проміжним програмним забезпеченням експрес-сесії на основі файлів cookie із socket.io. Працює з express> 4.0.0 і socket.io> 1.0.0 і не буде сумісним із зворотною функцією.

Працював у мене !!


Гей. Як би ви використовували значення сеансу в інтерфейсі? Я не бачу їх у документах npm.
Харі Рам,

1

Ви можете поглянути на це: https://github.com/bmeck/session-web-sockets

або ж ви можете використовувати:

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

Сподіваюся, це допомагає.


Я знаю сеансові веб-сокети, але я не хочу використовувати для цього бібліотеку, я шукаю просте рішення. Я спробував client.listener.server.viewHelpers; але він повернув це: {}
sfs

2
хоча спочатку це, здається, працює, це призводить до перегонових умов. Я пропоную вам повністю цього уникати.
Шріпад Кришна

1

Я не впевнений, що роблю це правильно. https://github.com/LearnBoost/socket.io/wiki/Authorizing

За допомогою даних рукостискання ви можете отримати доступ до файлів cookie. А в файлах cookie ви можете захопити connect.sid, який є ідентифікатором сеансу для кожного клієнта. А потім використовуйте connect.sid для отримання даних сеансу з бази даних (я припускаю, що ви використовуєте RedisStore)


це саме той шлях, але ви не круті, тому ви не можете отримати точки переповнення стека. github.com/tcr/socket.io-session та github.com/functioncallback/session.socket.io Мені подобається перший трохи кращий його очищувач. Другий - дещо краще задокументований.
Джеймс

@TJ Мені шкода за це, але ти розумієш, що відповідь була 2 роки тому? І це, мабуть, не спрацювало б зараз
Тан Нгуєн

@TanNguyen Я знаю, тому я повідомив вас, щоб ви могли оновити відповідь обов’язково, ніж вказувати людям на мертві посилання
TJ

@TJ Дякую за це. На жаль, я відійшов від socket.io через проблему з продуктивністю 2 роки тому. Тому я не знаю, яким є поточний спосіб ведення сесії в socket.io
Тан Нгуєн
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.