仅限套接字IO会话不会持久化

时间:2016-01-15 02:21:17

标签: node.js session express socket.io

我在我正在构建的聊天应用程序中使用Socket.io。我正在尝试设置会话,以便我可以在会话之间保持用户的登录。

以下是相关代码:

index.js (服务器)

var cookieParser = require('cookie-parser')();
var session = require('cookie-session')({ secret: 'secret' });

app.use(cookieParser);
app.use(session);

io.use(function(socket, next) {
    var req = socket.handshake;
    var res = {};
    cookieParser(req, res, function(err) {
        if (err) return next(err);
        session(req, res, next);
    });
});


io.on('connection', function(socket){

    socket.on('test 1', function(){
        socket.handshake.test = 'banana';
    });

    socket.on('test 2', function(){
        console.log(socket.handshake.test);
    });
});

chat.js (客户端)

var socket = io();

socket.emit('test 1');
socket.emit('test 2');

上面的代码有效,它会按预期将banana打印到控制台。但是,如果我像这样评论“测试1”:

var socket = io();

// socket.emit('test 1');
socket.emit('test 2');

它会将undefined打印到控制台。

它不应该仍然可以打印banana,因为它正在使用会话并且它在请求之间持续存在吗?如果我颠倒了我称之为'test 1'和'test 2'的顺序,我也会遇到同样的问题。

我做错了什么?我希望会议能够按预期持续下去吗?

2 个答案:

答案 0 :(得分:5)

问题是您使用的是cookie-session,而socket.io不允许您根据XMLHttpRequest的规范设置Cookie,而且您还没有request/response在Web套接字事务的中间,因此您无法设置响应cookie。

使用中间件,您可以看到cookie,但无法在socket.io中设置它。 这个例子可以确保这一点:

io.use(function(socket, next) {
    var req = socket.request;
    var res = req.res;
    cookieParser(req, res, function(err) {
        if (err) return next(err);
        session(req, res, next);
    });
});

io.on('connection', function(socket){
    var req = socket.request;
    console.log(req.session.test)

    socket.on('test 1', function(){
        req.session.test = 'banana';
    });

    socket.on('test 2', function(){
        console.log(req.session.test);
    });
});

app.get('/', function(req, res) {
    console.log(req.session.test)
    if (!req.session.test) {
      req.session.test = 'banana request'
    }
})      

您可以使用类似redis的内容来持久保存会话,或者使用某些“黑客”来设置握手。

另一个选项根本不使用会话,只需在socket对象或其他javascript对象中设置属性,但在这种情况下,您无法在服务器/服务之间共享对象。

答案 1 :(得分:1)

  1. 仍然可以访问标题。
  2. 您可以在服务器端为每个套接字保存数据:socket.my_value =“any data type”;
  3. 您可以在io.sockets对象中保存数据,io.my_value =“任何数据类型”
  4. 所以,例如:

        io.on('connection', function(socket){
            var id = socket.handshake.query.id; //you can set this in client connection string http://localhost?id=user_id
            //Validate user, registered etc. and if ok/
            if(validateUser(id)) {
                //if this is reconnect
                if(io.sessions[id]) {
                   socket.session_id = io.sessions[id].session_id;
                } else {
                   var session_id = random_value;
                   socket.session_id = some_random_value;
                   io.sessions[id] = {
                     user_id: id,
                     session_id: socket.session_id
                   };
                }
    
                registerEvent(socket);
            } else {
                socket.emit('auth_error', 'wrong user');
            }
        });
    
    
    function registerEvent(socket) {
        socket.on('some_event', function(data, callback) {
           if(!socket.session_id) {
             callback('unathorized');//or emit
             socket.emit('auth_error', 'unauthorized');
           }
    
           //do what you want, user is clear
        });
    }