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

Dro*_*own 10 session node.js 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);
    });
});
Run Code Online (Sandbox Code Playgroud)

chat.js(客户端)

var socket = io();

socket.emit('test 1');
socket.emit('test 2');
Run Code Online (Sandbox Code Playgroud)

上面的代码工作,它将banana按预期打印到控制台.但是,如果我像这样评论'test 1':

var socket = io();

// socket.emit('test 1');
socket.emit('test 2');
Run Code Online (Sandbox Code Playgroud)

它将打印undefined到控制台.

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

我究竟做错了什么?我期望会话能够如预期的那样持续存在吗?

Dei*_*idy 6

问题是你正在使用一个cookie-session,而socket.io不允许你设置cookie到期规格XMLHttpRequest,你也没有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'
    }
})      
Run Code Online (Sandbox Code Playgroud)

你可以使用类似的东西redis来持久化会话,或者一些"黑客"来在握手中设置它.

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