Socket.io и сеанс?

Я использую express framework. Я хочу получить данные сеанса из socket.io. Я попробовал выразить dynamicHelpers с данными 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
    }); 
});

Ответ 1

Это не сработает для сокетов, проходящих по транспорту 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!!!!
    });
  }
});

Затем вы можете использовать сеанс по мере необходимости.

Ответ 2

Решение Socket.IO-session предоставляет приложение для атак XSS, выставляя идентификатор сеанса на уровне клиента (скриптинга).

Проверьте это решение (для Socket.IO >= v0.7). См. Docs здесь.

Ответ 3

Я предлагаю не полностью изобретать колесо. Необходимые инструменты уже являются пакетом npm. Я думаю, что это то, что вам нужно: session.socket.io Я использую его в эти дни, и это будет очень полезно, я думаю!! Связывание экспресс-сессии с слоем socket.io будет иметь так много преимуществ!

Ответ 4

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


Я получил эту работу довольно аккуратно, не обойдя транспорт флэш-памяти в соответствии с вышеприведенным решением pr0zac. Я также использую экспресс с 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
    });
  });
});

В моем случае my session_store - это Redis, используя библиотеку redis-connect.

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

Надеюсь, что это поможет кому-то, кто находит этот пост при поиске в Google (как и я;)

Ответ 5

Смотрите это: Аутентификация Socket.IO

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

Ответ 6

Проверьте Socket.IO-connect

Подключить WebSocket Middleware Wrapper вокруг Socket.IO- node https://github.com/bnoguchi/Socket.IO-connect

Это позволит вам проталкивать запросы Socket.IO вниз по стеку промежуточного программного обеспечения Express/Connect, прежде чем обрабатывать его с помощью обработчиков событий Socket.IO, предоставляя вам доступ к сеансу, куки и многое другое. Хотя, я не уверен, что он работает со всеми транспортными средствами Socket.IO.

Ответ 7

Вы можете посмотреть на это: https://github.com/bmeck/session-web-sockets

или, альтернативно, вы можете использовать:

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

Надеюсь, что это поможет.

Ответ 8

Я не уверен, что делаю все правильно. https://github.com/LearnBoost/socket.io/wiki/Authorizing

С помощью данных рукопожатия вы можете получить доступ к файлам cookie. И в файлах cookie вы можете захватить connect.sid, который является идентификатором сеанса для каждого клиента. И затем используйте connect.sid для получения данных сеанса из базы данных (я предполагаю, что вы используете RedisStore)

Ответ 9

Вы можете использовать express-socket.io-session.

Поделитесь промежуточным программным обеспечением экспресс-сессии на основе файлов cookie с socket.io. Работает с express > 4.0.0 и socket.io > 1.0.0 и не будет обратно совместимым.

Работал для меня!

Ответ 10

Этот код содержит промежуточное программное обеспечение сокетов, которое соединяется с Express. req.session сеанса также и отправьте переменную req.session обратно клиенту. В этом случае клиенту нужен слушатель, socket.on('auth', function(session) { }) чтобы получить последнюю информацию!

  var express = require('express'),
  app = express()
  var expressSession = require('express-session'),
  sessionMiddleware = {}
  sessionMiddleware = expressSession({
    genid: req => {
      return (require('uuid/v4'))()
    },
    store: new redisStore(),
    secret: '*******************************',
    name: process.env.NODE_ENV ? 'live_session' : 'dev_session',
    resave: false,
    saveUninitialized: false,    
    proxy: true,
    logErrors: true,
    unset: 'keep',
    rolling: false,
    cookie: {
      domain: process.env.NODE_ENV ? '.indospace.io' : '.indo.io',
      secure: process.env.NODE_ENV ? true : false,
      httpOnly: true,
      expires: new Date(Date.now() + 3600000),
      maxAge: 3600000,
      sameSite: true
    }
  })

  app.use(sessionMiddleware)
      var http = require('http')
      http.globalAgent.maxSockets = Infinity
      app.server = http.Server(app)
      // parseInt(app.nconf.get('app:port')) + (process.env.NODE_APP_INSTANCE ? parseInt(process.env.NODE_APP_INSTANCE) : 0)
      app.server.listen(app.nconf.get('app:port'), '0.0.0.0', ret => {
        app.sio = require('socket.io').listen(app.server, {
          transports: ['websocket']
        })
        /*app.sio.adapter(require('socket.io-redis')({
           host: 'localhost',
           port: 6379
        }))*/
        app.sio.use((socket, next) => {
          var socket_subdomain = socket.handshake.headers.host.split('.')[0]
          console.log('socket subdomain: ' + socket_subdomain)
          sessionMiddleware(socket.handshake, {}, err => {
            socket.on('auth', sock => {
              socket.handshake.session.reload(err => {
                console.log(Object.keys(socket.handshake.session))
                console.log('*'.repeat(100))
                app.sio.sockets.in('room_' + socket.handshake.session.id).emit('auth', socket.handshake.session)
              })
            })
          })
          sessionMiddleware(socket.request, {}, next)
        })
        app.sio.sockets.on('connection', socket => {
          socket.join('room_' + socket.request.session.id)
          app.sio.sockets.in('room_' + socket.request.session.id).emit('auth', socket.request.session)
        })
        app.sio.sockets.on('disconnect', ret => {
          console.log(app.colors.red('[socket disconnected]'))
          // drop session ID from Redis somehow???
        })
      })