为什么socket-io的get无法从持久会话中获取数据?

时间:2013-01-31 11:37:01

标签: node.js express socket.io

这里我使用的是socket-io,并且每次重新加载它都会给我新的值(理想情况下它应该来自session并且应该相同)。你能指出原因吗?

var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
var _ = require('lodash');
var q = require('q');

server.listen(3000);

var userCounter = 0;
    app.use(express.cookieParser());
    app.use(express.cookieSession({secret: 'secret', key: 'express.sid', cookie:{ path: '/', httpOnly: true, maxAge: (1000*3600*24)} }));
    app.use(express.static('public'))
   .use(function (req, res) {
        res.end('File not available\n');
    });

function getUserName(socket) {
    var deferred = q.defer();
    socket.get('userName', function (err, Name) {
        if (err || !Name) { // PROBLEM: It always goes in to this IF
            var userName = "Userno: " + (userCounter + 1);
            userCounter++;
            socket.set('userName', userName, function () {
                deferred.resolve(userName);
            });
        } else {
            deferred.resolve(Name);
        }
    });
    return deferred.promise;
}

io.sockets.on('connection', function (socket) {
    getUserName(socket).
        then(function (userName) {
            socket.emit("welcome", userName);
            _(io.sockets.sockets).forEach(function (eSocket) {
                if (socket !== eSocket)
                    eSocket.emit("userAdded", userName);
            });
            socket.on('disconnect', function () {
                socket.get('userName', function (err, userName) {
                    io.sockets.emit('userRem', userName);
                });
            });
        });

});

1 个答案:

答案 0 :(得分:4)

您尚未为socket.io实施任何会话身份验证。默认情况下,与socket.io的每个连接都是新连接,但它具有相同的cookie(cookie中的session_id)。 socket.io special option通过身份验证功能传递每个请求,如:

var sAuthorization = function(req, cb) {
    if ( req.headers.cookie ) { 
        cb(null, true); return; // We have cookie
    } else {
        cb(null, false); return; // We don't have cookie drop the connection
    };

var socket = require('socket.io').listen(app, { authorization: sAuthorization });

你应该做些什么来使它工作(我不会把它写成代码,因为需要进行大量的修改):

  1. 实施为用户在快递中的初始http连接中提供名称(每个用户都应获得其唯一会话的用户名);
  2. 实现sessionStore,可以通过express& amp; socket.io(请参阅this gist了解如何操作(它使用nowjs,但它是你必须查看的sessionStore代码)。实际上,如果你将sessionStore放在某个数据库中,而不是在你的MemoryStore。
  3. 让您的socket.io授权子进入此会话商店并获取用户名,然后照常将其作为此套接字的参数放置:socket.set('name', ....
  4. 差不多就是这样。它并不像听起来那么难,但这是正确的做法。

    进一步阅读:

    1. https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO
    2. https://github.com/LearnBoost/socket.io/wiki/Authorizing
    3. 更新:

      看看这个答案,它对你很有帮助 Securing Socket.io

      更新II:

      我在这里用代码https://gist.github.com/1b17fd2a7b324cb3411a

      创建了一个Gist文件
      var express = require('express'),
          app = express(),
          http = require('http'),
          server = http.createServer(app),
          users = 0,
          MemoryStore = express.session.MemoryStore,
          sessionStore = new MemoryStore(),
          parseCookie = require('cookie').parse,
          utils = require('connect').utils,
          io = require('socket.io').listen(server);
      
      app.use( express.bodyParser() );
      app.use( express.cookieParser('secret') );
      app.use( express.session({secret: 'secret', store:sessionStore}) );
      
      app.get('/', function(req, res) {
          var user = req.session.username ? req.session.username : null;
          if ( !user ) {
              user = 'user_' + users++;
              req.session.username = user;
              req.session.save();
          }
          res.send('<!doctype html> \
              <html> \
              <head><meta charset="utf-8"></head> \
              <body> \
                  <center>Welcome ' + user + '</center> \
                  <script src="/socket.io/socket.io.js"></script> \
                  <script> \
                      var socket = io.connect(); \
                      socket.emit("message", "Howdy"); \
                  </script> \
              </body> \
              </html>');
      });
      
      io.configure(function () {
          io.set('authorization', function (request, callback) {
              var cookie = parseCookie(request.headers.cookie);
              if( !cookie && !cookie['connect.sid'] ) {
                  return callback(null, false);
              } else {
                  sessionStore.get(utils.parseSignedCookie(cookie['connect.sid'], 'secret'), function (err, session) {
                      if ( err ) {
                          callback(err.message, false);
                      } else {
                          if ( session && session.username ) {
                              request.user = session.username;
                              callback(null, true);
                          } else {
                              callback(null, false);
                          }
                      }
                  });
              }
          });
      });
      
      io.sockets.on('connection', function (socket) {
          socket.on('message', function(msg) {
              console.log(msg + 'from '+ socket.handshake.user);
          });
      });
      
      server.listen(8000);