如何在Socket.io/express-sessions中访问/保存授权事件的会话数据?

时间:2022-09-02 23:56:08

I setup a websocket using Socket.io and express 4 framework on node.js server.

我使用Socket.io设置了一个websocket,并在node.js服务器上表达了4个框架。

I am trying to implement authorization step for my users when using my websocket.

我正在尝试在使用websocket时为我的用户实施授权步骤。

When a user connects, a token is passed as a query value to the server. At the server level, I query a database for a session that match the passed token. If a session is found, I do few other check to ensure that the token is not hijacked.

当用户连接时,令牌将作为查询值传递给服务器。在服务器级别,我在数据库中查询与传递的令牌匹配的会话。如果找到会话,我会做其他一些检查以确保令牌未被劫持。

Problem

The session data seems to be cleared on every page reload. Or the server is failing to link the sessionId to the user who created it so everytime it generates a new session.

会话数据似乎在每次重新加载页面时都被清除。或者服务器无法将sessionId链接到创建它的用户,因此每次生成新会话时都是如此。

I am puzzled on how to access the session variables "if they are set."

我很困惑如何访问会话变量“如果它们被设置。”

My Code's Problem

我的代码问题

When a user reload his/her page/client, the session data will become undefined on the new request. The session is good until the page is refreshed which is my problem. I need to be able to keep the session active even after the user refresh their page.

当用户重新加载他/她的页面/客户端时,会话数据将在新请求中变为未定义。会话很好,直到页面刷新,这是我的问题。即使用户刷新页面,我也需要能够保持会话处于活动状态。

Questions

How can ensure that the session data are not cleared on every page refresh?

如何确保在每次刷新页面时都不清除会话数据?

Here is my authorization code

这是我的授权码

io.set('authorization', function (handshakeData, accept) {

    var session = handshakeData.session || {};

    //This is always undefined!
    console.log('Session Data:' + session.icwsSessionId);

    //var cookies = handshakeData.headers.cookie;
    var token = handshakeData._query.tokenId || '';
    //console.log('Token: ' + token);

    if(!token){
        console.log('Log: token was not found');
        return accept('Token was found.', false);
    }

    //allow any user that is authorized
    if(session && session.autherized && token == session.token){
        console.log('Log: you are good to go');
        return accept('You are good to go', true);
    }

    //if the client changed their token "client logged out"
    //terminate the open session before opening a new one
    if (session.autherized && token != session.token){

        var icwsConnection = new icwsConn(icwsRequest);
        icwsRequest.setConnection(session.icwsServer, session.icwsPort);
        icwsRequest.setIcwsHeaders(session.icwsSessionId, session.icwsToken);
        icwsConnection.logout();

        session.autherized = false;
        session.token = null;
        session.icwsServer = null;
        session.icwsPort = null;
        session.icwsSessionId = null;
        session.icwsToken = null;

        icwsConnection = null;
    }

Here is my entire code if needed

如果需要,这是我的整个代码

var env = require('./modules/config'),
    app = require('express')(),
    https = require('https'),
    fs = require('fs'),
    session = require('express-session'),
    redisStore = require("connect-redis")(session),
    sharedsession = require("express-socket.io-session"),
    base64url = require('base64url');

const server = https.createServer(
    {
        key: fs.readFileSync('certs/key.pem'),
        cert: fs.readFileSync('certs/cert.pem')
    }, function (req, res){
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
    }
).listen(env.socket.port, env.socket.host, function () {
    console.log('\033[2J');
    console.log('Websocket is running at https://%s:%s', server.address().address, server.address().port);
});

var io = require('socket.io')(server);

const sessionMiddleware = session({
    store: new redisStore({
        host: env.redis.host,
        port: env.redis.port
    }),
    secret: env.session.secret,
    name: env.session.name,
    rolling: false,
    resave: true,
    saveUninitialized: true
});

app.use(sessionMiddleware);


// Use shared session middleware for socket.io
// setting autoSave:true
io.use(sharedsession(sessionMiddleware, {
    autoSave: true
})); 


var icwsReq = require('./modules/icws/request.js'),
    icwsConn = require('./modules/icws/connection.js'),
    icwsInter = require('./modules/icws/interactions.js'),
    sessionValidator = require('./modules/validator.js');

var clients = {};
var icwsRequest = new icwsReq();
var sessionChecker = new sessionValidator();



app.get('/', function (req, res) {
    res.send('welcome');
});

io.set('authorization', function (handshakeData, accept) {

    var session = handshakeData.session || {};

    //This is always undefined!
    console.log('Session Data:' + session.icwsSessionId);

    //var cookies = handshakeData.headers.cookie;
    var token = handshakeData._query.tokenId || '';
    //console.log('Token: ' + token);

    if(!token){
        console.log('Log: token was not found');
        return accept('Token was found.', false);
    }

    //allow any user that is authorized
    if(session && session.autherized && token == session.token){
        console.log('Log: you are good to go');
        return accept('You are good to go', true);
    }

    /*
    if (!originIsAllowed(origin)) {
        // Make sure we only accept requests from an allowed origin
        socket.destroy();
        console.log((new Date()) + ' Connection from origin ' + origin + ' rejected.');
        return false;
    }
    */

    //if the client changed their token "client logged out"
    //terminate the open session before opening a new one
    if (session.autherized && token != session.token){

        var icwsConnection = new icwsConn(icwsRequest);
        icwsRequest.setConnection(session.icwsServer, session.icwsPort);
        icwsRequest.setIcwsHeaders(session.icwsSessionId, session.icwsToken);
        icwsConnection.logout();

        session.autherized = false;
        session.token = null;
        session.icwsServer = null;
        session.icwsPort = null;
        session.icwsSessionId = null;
        session.icwsToken = null;

        icwsConnection = null;
    }

    var myIP = '10.0.4.195';

    var decodedToken = base64url.decode(token);

    sessionChecker.validateData(decodedToken, myIP, env.session.duration, function(isValid, icws){

        if(isValid){

            session.authorized = true;
            session.icwsServer = icws.host;
            session.icwsPort = icws.port;
            session.token = token;
            session.icwsSessionId = null;
            session.icwsToken = null;

            icwsRequest.setConnection(icws.host, icws.port);
            var icwsConnection = new icwsConn(icwsRequest);

            icwsConnection.login(icws.username, icws.password, function(isLogged, icwsSession, headers){

                if(isLogged && icwsSession.sessionId && icwsSession.csrfToken){

                    //icwsConnection.setWorkstation(icws.workstaton);
                    session.icwsSessionId = icwsSession.sessionId;
                    session.icwsToken = icwsSession.csrfToken;

                    icwsRequest.setIcwsHeaders(session.icwsSessionId, session.icwsToken);
                    console.log('Log: new connection to ICWS! ' + session.icwsSessionId );
                }

            });

            console.log('Log: new connection to websocket!')
            return accept('New connection to websocket!', true);

        } else {

            console.log('Log: token could not be validated!');
            return accept('Token could not be validated!', false);
        }

    });

});


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


    console.log('Authorized Session! Websocket id ready for action!');
    //var origin = socket.request.headers.origin || '';
    //var myIP = socket.request.socket.remoteAddress || '';

    if(!socket.request.sessionID){
        console.log('Missing Session ID');
        return false;
    }

    var socketId = socket.id;
    var sessionID = socket.request.sessionID;


    //Add this socket to the user's connection
    if(userCons.indexOf(socketId) == -1){
        userCons.push(socketId);
    }

    clients[sessionID] = userCons;

    console.log(clients); //display all connected clients

    socket.on('placeCall', function(msg){

        icwsInter.call(method, uri, params, header, true);

    });

    socket.on('chat', function(msg){
        console.log('Chat Message: ' + msg);
        socket.emit('chat', { message: msg });
    });


    socket.on('disconnect', function(msg){
        console.log('Closing sessionID: ' + sessionID);
        var userCons = clients[sessionID] || [];

        var index = userCons.indexOf(socketId);

        if(index > -1){
            userCons.splice(index, 1);
            console.log('Removed Disconnect Message: ' + msg);
        } else {
            console.log('Disconnect Message: ' + msg);
        }

    }); 

    socket.on('error', function(msg){
        console.log('Error Message: ' + msg);
    }); 

});


function originIsAllowed(origin) {
    // put logic here to detect whether the specified origin is allowed.
        var allowed = env.session.allowedOrigins || []

        if(allowed.indexOf(origin) >= 0){
            return true;
        }

    return false;
}

Edited

The io cookie changes on every request. When a io cookie is created it will have a last accessed values of 12/31/1969 4:00:00 PM

每个请求都会更改io cookie。创建io cookie时,它的最后访问值为12/31/1969 4:00:00 PM

Also, this cookie changes on every page reload.

此外,此cookie在每次重新加载页面时都会更改。

After @Osk suggestion below Here is my new code which is still isn't saving my session data on page reload.

在下面的@Osk建议之后这是我的新代码,它仍然没有在页面重新加载时保存我的会话数据。

var env = require('./modules/config'),
    app = require('express')(),
    https = require('https'),
    fs = require('fs'),
    session = require('express-session'),
    redisStore = require("connect-redis")(session),
    sharedsession = require("express-socket.io-session"),
    base64url = require('base64url'),
    cookieParser = require("cookie-parser");

const server = https.createServer(
    {
        key: fs.readFileSync('certs/key.pem'),
        cert: fs.readFileSync('certs/cert.pem')
    }, function (req, res){
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
    }
).listen(env.socket.port, env.socket.host, function () {
    console.log('\033[2J');
    console.log('Websocket is running at https://%s:%s', server.address().address, server.address().port);
});

var io = require('socket.io')(server);
var sessionStore = new redisStore({
        host: env.redis.host,
        port: env.redis.port
    });

const sessionMiddleware = session({
        store: sessionStore,
        secret: env.session.secret,
        name: env.session.name,
        rolling: true,
        resave: false,
        saveUninitialized: false,
        cookie: { 
            maxAge: 60 * 60 * 1000
        }
    });


app.use(sessionMiddleware);

// Use shared session middleware for socket.io
// setting autoSave:true
io.use(sharedsession(sessionMiddleware, {
    autoSave: false
})); 

var icwsReq = require('./modules/icws/request.js'),
    icwsConn = require('./modules/icws/connection.js'),
    icwsInter = require('./modules/icws/interactions.js'),
    sessionValidator = require('./modules/validator.js');

var clients = {};

var icwsRequest = new icwsReq();
var sessionChecker = new sessionValidator();



app.get('/', function (req, res) {
    res.send('welcome');
});


//Middleware for authorizing a user before establishing a connection
io.use(function(socket, next) {


    var origin = socket.request.headers.origin || '';

    if (!originIsAllowed(origin)) {
        // Make sure we only accept requests from an allowed origin
        socket.destroy();
        console.log((new Date()) + ' Connection from origin ' + origin + ' rejected.');
        return false;
    }

    var myIP = socket.request.socket.remoteAddress || '';
    var token = socket.handshake.query.tokenId || '';
    var session = socket.handshake.session || {};

    //This should be defined on a reload
    console.log('IP Address: ' + myIP + '      SessionID: ' + socket.handshake.sessionID);

    if(!token){
        console.log('Log: token was not found');
        return next(new Error('Token not found'));
    }

    //allow any user that is authorized
    if(session && session.autherized && token == session.token){
        console.log('Log: you are good to go');
        return next(new Error('You are good to go'));
    }

    //if the client changed their token "client logged out"
    //terminate the open session before opening a new one
    if (session.autherized && token != session.token){

        var icwsConnection = new icwsConn(icwsRequest);
        icwsRequest.setConnection(session.icwsServer, session.icwsPort);
        icwsRequest.setIcwsHeaders(session.icwsSessionId, session.icwsToken);
        icwsConnection.logout();

        session.autherized = false;
        session.token = null;
        session.icwsServer = null;
        session.icwsPort = null;
        session.icwsSessionId = null;
        session.icwsToken = null;
        icwsConnection = null;
        session.save();
    }

    var decodedToken = base64url.decode(token);

    sessionChecker.validateData(decodedToken, myIP, env.session.duration, function(isValid, icws){

        if(isValid){

            session.authorized = true;
            session.icwsServer = icws.host;
            session.icwsPort = icws.port;
            session.token = token;
            session.icwsSessionId = null;
            session.icwsToken = null;

            icwsRequest.setConnection(icws.host, icws.port);
            var icwsConnection = new icwsConn(icwsRequest);
            /*
            icwsConnection.login(icws.username, icws.password, function(isLogged, icwsSession, headers){

                if(isLogged && icwsSession.sessionId && icwsSession.csrfToken){

                    //icwsConnection.setWorkstation(icws.workstaton);
                    session.icwsSessionId = icwsSession.sessionId;
                    session.icwsToken = icwsSession.csrfToken;

                    icwsRequest.setIcwsHeaders(session.icwsSessionId, session.icwsToken);
                    console.log('Log: new connection to ICWS! ' + session.icwsSessionId );
                }

            });
            */
            session.save(function(){
                console.log('Log: new connection to websocket!');   
            });

            return next();

        } else {

            console.log('Log: token could not be validated!');
            return next(new Error('Token could not be validated!'));
        }

    });

});


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

    console.log('Connection is validated and ready for action!');

    var socketId = socket.id;

    if(!socket.handshake.sessionID){
        console.log('sessionId was not found');
        return false;
    }

    var sessionID = socket.handshake.sessionID;
    var userCons = clients[sessionID] || [];

    //Add this socket to the user's connection
    if(userCons.indexOf(socketId) == -1){
        userCons.push(socketId);
    }

    clients[sessionID] = userCons;

    //console.log(clients);

    socket.on('placeCall', function(msg){

        icws.call(method, uri, params, header, true);

    });

    socket.on('chat', function(msg){
        console.log('Chat Message: ' + msg);
        socket.emit('chat', { message: msg });
    });


    socket.on('disconnect', function(msg){
        console.log('Closing sessionID: ' + sessionID);
        var userCons = clients[sessionID] || [];

        var index = userCons.indexOf(socketId);

        if(index > -1){
            userCons.splice(index, 1);
            console.log('Removed Disconnect Message: ' + msg);
        } else {
            console.log('Disconnect Message: ' + msg);
        }

    }); 

    socket.on('error', function(msg){
        console.log('Error Message: ' + msg);
    }); 

});


function originIsAllowed(origin) {
    // put logic here to detect whether the specified origin is allowed.
        var allowed = env.session.allowedOrigins || []

        if(allowed.indexOf(origin) >= 0){
            return true;
        }

    return false;
}

2 个解决方案

#1


3  

Which version of socket.io are you using?

你使用的是哪个版本的socket.io?

express-socket.io-session works with socket.io 1.x

express-socket.io-session与socket.io 1.x一起使用

I see you're calling io.set() which is deprecated on socket.io 1.x

我看到你正在调用在socket.io 1.x上弃用的io.set()

For more on this, take a look at http://socket.io/docs/migrating-from-0-9/ under the title Authentication differences. There, it's stated that

有关这方面的更多信息,请查看标识身份验证差异下的http://socket.io/docs/migrating-from-0-9/。在那里,它说明了

The old io.set() and io.get() methods are deprecated and only supported for backwards compatibility."

旧的io.set()和io.get()方法已弃用,仅支持向后兼容。“

Could this be related to your issue ?

这可能与您的问题有关吗?

When you install the express-socket.io-session package, there's an example directory inside the package. It may come in handy to test against a working example for this module.

安装express-socket.io-session软件包时,软件包中有一个示例目录。针对此模块的工作示例进行测试可能会派上用场。

#2


1  

Here is a working example of how you can share sessions between express and socket.io, even when they are not on the same domain.

下面是一个工作示例,说明如何在express和socket.io之间共享会话,即使它们不在同一个域中。

(You can find a slightly different git repository with a running example here https://github.com/dievardump/express-socket-auth )

(你可以在这里找到一个稍微不同的git存储库和一个运行的例子https://github.com/dievardump/express-socket-auth)

I simply use express-session, I don't see why using another middleware, since it works perfectly with socket.io

我只是使用快速会话,我不明白为什么使用另一个中间件,因为它与socket.io完美配合

Since I do not have redis accessible, I used require('session-file-store') for the shared sessions.

由于我没有可访问的redis,因此我使用require('session-file-store')进行共享会话。

Problem

Problem comes from the cross-domain policy which won't let you share the connect.sid Cookie value.

问题来自跨域策略,它不允许您共享connect.sid Cookie值。

A workaround is :

解决方法是:

  • serve non-httpOnly session cookies from the host (here for me server.dev). [express.js line 16]

    从主机提供非httpOnly会话cookie(这里是我的server.dev)。 [express.js第16行]

  • read via JavaScript and send the connect.sid value as a sessionId parameter when connection to socket.io [client.js line 26:30]

    通过JavaScript读取并在连接到socket.io [client.js第26:30行]时将connect.sid值作为sessionId参数发送

  • when handshaking adding the value of connect.sid=socket.handshake.query.sessionId to the socket.handshake.headers.cookie before reading the handshake with the session middleware [socket.js line 32:37]

    握手时,在读取与会话中间件的握手之前,将connect.sid = socket.handshake.query.sessionId的值添加到socket.handshake.headers.cookie [socket.js line 32:37]

Architecture

Here followed :

接下来是:

  • server.js which require

    需要的server.js

    • express.js : Create express server accessed on my computer via http://server.dev:3000

      express.js:通过http://server.dev:3000创建在我的计算机*问的快速服务器

      • serve HTML

      • create Sessions when loading page

        加载页面时创建会话

    • socket.js : Create Socket.io server accessed on my computer via http://socket.dev:8000

      socket.js:通过http://socket.dev:8000创建在我的计算机*问的Socket.io服务器

  • client.js

    • served on http://server.dev:3000

      在http://server.dev:3000上提供

    • connect to socket server on http://socket.dev:8000

      连接到http://socket.dev:8000上的套接字服务器

Tests

Steps to test I used here :

我在这里使用的测试步骤:

  • Client open the page

    客户打开页面

  • If the cookie key connect.sid is not set

    如果未设置cookie密钥connect.sid

    • Client tries to connect to Socket.io : Connection error : [Not authenticated]

      客户端尝试连接到Socket.io:连接错误:[未经过身份验证]

    • Client calls /authenticate

      客户端呼叫/验证

      • session is generated
      • 会话生成

    • Client tries to connect to Socket.io with value of connect.sid as sessionId parameter : Connection sucessfull

      客户端尝试使用connect.sid的值连接到Socket.io作为sessionId参数:Connection sucessfull

  • If cookie connect.sid is set

    如果设置了cookie connect.sid

    • Client tries to connect to Socket.io with value of connect.sid as sessionId parameter : Connection sucessfull
    • 客户端尝试使用connect.sid的值连接到Socket.io作为sessionId参数:Connection sucessfull

Files

server.js

require('./express');
require('./socket');

express.js

    var express = require('express');
var app = express();
var http = require('http');
var io = require('socket.io');
var bodyParser = require('body-parser');
var sessionExpress = require('express-session');
var FileStore = require('session-file-store')(sessionExpress);

var secret = 'keyboard cat';
var session = sessionExpress({
    secret: secret,
    store: new FileStore(),
    resave: true,
    saveUninitialized: true,
    cookie: { 
        httpOnly: false, // important to allow client to read session cookie with JavaScript
        maxAge: 60 * 60 * 1000
    }
});

app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(express.static(__dirname));

app.use('/authenticate', session);
app.get('/authenticate', function(req, res) {
    var session = req.session;
    session.userdata = session.userdata || {};
    session.userdata.connected = true;
    session.save(function(err) {
        if (err) {
            connectionError(res, session);
        } else {
            res.status(200);
            res.send();
        }
    });
});

// routes
app.get('/', function(req, res) {
    res.send('welcome');
});

// setup servers
var server = http.createServer(app);
server.listen(3000);

socket.js

var express = require('express');
var app = express();
var http = require('http');
var io = require('socket.io');
var sessionExpress = require('express-session');
var FileStore = require('session-file-store')(sessionExpress);

var secret = 'keyboard cat';
var sessionIdKey = 'connect.sid';

var session = sessionExpress({
    secret: secret,
    store: new FileStore(),
    resave: true,
    saveUninitialized: true,
    cookie: { 
        maxAge: 60 * 60 * 1000
    }
});

// setup servers
var server = http.createServer(app, function (req, res){
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
});

server.listen(8000);

var sio = io(server);
sio.use(function(socket, accept) {        
    // writing sessionId, sent as parameter, on the socket.handshake cookies
    if (socket.handshake.query.sessionId) {
        var cookies = (socket.handshake.headers.cookie || '').split(';');
        cookies.push(sessionIdKey + '=' + socket.handshake.query.sessionId);
        socket.handshake.headers.cookie = cookies.join(';');
    }
    session(socket.handshake, {}, function(err) {
        if (err) return accept(err);
        console.log('User trying to connect to Socket.io');
        var session = socket.handshake.session,
            userData = session.userdata || {};

        // is connected and good
        if (!userData || !userData.connected) {
            console.log('----- User has no active session, error');
            accept(new Error('Not authenticated'));
        } else {
            console.log('----- Socket.io connection attempt successful');
            accept(null, session.userid !== null);
        }
    });
});


sio.on('connection', function (socket) {
    console.log('Connection');
});

client.js

        function getCookie(name) {
            var value = "; " + document.cookie;
            var parts = value.split("; " + name + "=");
            if (parts.length == 2) return decodeURIComponent(parts.pop().split(";").shift());
        }

        function fetch(url, data, callback) {
            try {
                var x = new XMLHttpRequest();
                x.open(data ? 'POST' : 'GET', url, 1);
                x.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
                x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
                x.onreadystatechange = function () {
                    x.readyState > 3 && callback && callback(x.responseText, x);
                };
                x.send(data || null);
            } catch (e) {
                window.console && console.log(e);
            }
        };


        function connectServer(cb) {
            var sessionId = getCookie('connect.sid');
            var data = { forceNew: true, query : {  } };
            if (sessionId) {
                data.query.sessionId = sessionId
            }

            console.log('Trying to connect to Socket.io server');

            var server = io('http://socket.dev:8000', data);
            server.on('error', function (err) {
                console.log('----- Connection error : [%s]', err);
                setTimeout(function () {
                    cb();
                }, 200);
            });
            server.on('connect', function (data) {
                console.log('----- Connection successful with sessionId [%s]', sessionId);
                setTimeout(function () {
                    cb();
                }, 200);
            });
        }

        if (getCookie('connect.sid')) {
            console.log('Session cookie Detected');
            connectServer(function () { });
        } else {
            connectServer(function () {
                console.log('Call ./authenticate to create session server side');
                fetch('./authenticate', null, function () {
                    console.log('Session created')
                    connectServer(function () {});
                }); 
            }); 
        }

Execution

First Page loading Results

首页加载结果

Client :

Trying to connect to Socket.io server
----- Connection error : [Not authenticated]
Call ./authenticate to create session server side
Session created
Trying to connect to Socket.io server
----- Connection successful with sessionId [s:Ir9dVPi8wzplPCoeNXAsDlOkhL8AW0gx.wwzUQ2jftntWEc6lRdYqGxRBoszjPtjT4dBW/KjFIXQ]

Server :

User trying to connect to Socket.io
----- User has no active session, error
User trying to connect to Socket.io
----- Socket.io connection attempt successful
Connection

Reload page

Client :

Session cookie Detected
Trying to connect to Socket.io server
----- Connection successful with sessionId [s:Ir9dVPi8wzplPCoeNXAsDlOkhL8AW0gx.wwzUQ2jftntWEc6lRdYqGxRBoszjPtjT4dBW/KjFIXQ]

Server :

User trying to connect to Socket.io
----- Socket.io connection attempt successful
Connection

#1


3  

Which version of socket.io are you using?

你使用的是哪个版本的socket.io?

express-socket.io-session works with socket.io 1.x

express-socket.io-session与socket.io 1.x一起使用

I see you're calling io.set() which is deprecated on socket.io 1.x

我看到你正在调用在socket.io 1.x上弃用的io.set()

For more on this, take a look at http://socket.io/docs/migrating-from-0-9/ under the title Authentication differences. There, it's stated that

有关这方面的更多信息,请查看标识身份验证差异下的http://socket.io/docs/migrating-from-0-9/。在那里,它说明了

The old io.set() and io.get() methods are deprecated and only supported for backwards compatibility."

旧的io.set()和io.get()方法已弃用,仅支持向后兼容。“

Could this be related to your issue ?

这可能与您的问题有关吗?

When you install the express-socket.io-session package, there's an example directory inside the package. It may come in handy to test against a working example for this module.

安装express-socket.io-session软件包时,软件包中有一个示例目录。针对此模块的工作示例进行测试可能会派上用场。

#2


1  

Here is a working example of how you can share sessions between express and socket.io, even when they are not on the same domain.

下面是一个工作示例,说明如何在express和socket.io之间共享会话,即使它们不在同一个域中。

(You can find a slightly different git repository with a running example here https://github.com/dievardump/express-socket-auth )

(你可以在这里找到一个稍微不同的git存储库和一个运行的例子https://github.com/dievardump/express-socket-auth)

I simply use express-session, I don't see why using another middleware, since it works perfectly with socket.io

我只是使用快速会话,我不明白为什么使用另一个中间件,因为它与socket.io完美配合

Since I do not have redis accessible, I used require('session-file-store') for the shared sessions.

由于我没有可访问的redis,因此我使用require('session-file-store')进行共享会话。

Problem

Problem comes from the cross-domain policy which won't let you share the connect.sid Cookie value.

问题来自跨域策略,它不允许您共享connect.sid Cookie值。

A workaround is :

解决方法是:

  • serve non-httpOnly session cookies from the host (here for me server.dev). [express.js line 16]

    从主机提供非httpOnly会话cookie(这里是我的server.dev)。 [express.js第16行]

  • read via JavaScript and send the connect.sid value as a sessionId parameter when connection to socket.io [client.js line 26:30]

    通过JavaScript读取并在连接到socket.io [client.js第26:30行]时将connect.sid值作为sessionId参数发送

  • when handshaking adding the value of connect.sid=socket.handshake.query.sessionId to the socket.handshake.headers.cookie before reading the handshake with the session middleware [socket.js line 32:37]

    握手时,在读取与会话中间件的握手之前,将connect.sid = socket.handshake.query.sessionId的值添加到socket.handshake.headers.cookie [socket.js line 32:37]

Architecture

Here followed :

接下来是:

  • server.js which require

    需要的server.js

    • express.js : Create express server accessed on my computer via http://server.dev:3000

      express.js:通过http://server.dev:3000创建在我的计算机*问的快速服务器

      • serve HTML

      • create Sessions when loading page

        加载页面时创建会话

    • socket.js : Create Socket.io server accessed on my computer via http://socket.dev:8000

      socket.js:通过http://socket.dev:8000创建在我的计算机*问的Socket.io服务器

  • client.js

    • served on http://server.dev:3000

      在http://server.dev:3000上提供

    • connect to socket server on http://socket.dev:8000

      连接到http://socket.dev:8000上的套接字服务器

Tests

Steps to test I used here :

我在这里使用的测试步骤:

  • Client open the page

    客户打开页面

  • If the cookie key connect.sid is not set

    如果未设置cookie密钥connect.sid

    • Client tries to connect to Socket.io : Connection error : [Not authenticated]

      客户端尝试连接到Socket.io:连接错误:[未经过身份验证]

    • Client calls /authenticate

      客户端呼叫/验证

      • session is generated
      • 会话生成

    • Client tries to connect to Socket.io with value of connect.sid as sessionId parameter : Connection sucessfull

      客户端尝试使用connect.sid的值连接到Socket.io作为sessionId参数:Connection sucessfull

  • If cookie connect.sid is set

    如果设置了cookie connect.sid

    • Client tries to connect to Socket.io with value of connect.sid as sessionId parameter : Connection sucessfull
    • 客户端尝试使用connect.sid的值连接到Socket.io作为sessionId参数:Connection sucessfull

Files

server.js

require('./express');
require('./socket');

express.js

    var express = require('express');
var app = express();
var http = require('http');
var io = require('socket.io');
var bodyParser = require('body-parser');
var sessionExpress = require('express-session');
var FileStore = require('session-file-store')(sessionExpress);

var secret = 'keyboard cat';
var session = sessionExpress({
    secret: secret,
    store: new FileStore(),
    resave: true,
    saveUninitialized: true,
    cookie: { 
        httpOnly: false, // important to allow client to read session cookie with JavaScript
        maxAge: 60 * 60 * 1000
    }
});

app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(express.static(__dirname));

app.use('/authenticate', session);
app.get('/authenticate', function(req, res) {
    var session = req.session;
    session.userdata = session.userdata || {};
    session.userdata.connected = true;
    session.save(function(err) {
        if (err) {
            connectionError(res, session);
        } else {
            res.status(200);
            res.send();
        }
    });
});

// routes
app.get('/', function(req, res) {
    res.send('welcome');
});

// setup servers
var server = http.createServer(app);
server.listen(3000);

socket.js

var express = require('express');
var app = express();
var http = require('http');
var io = require('socket.io');
var sessionExpress = require('express-session');
var FileStore = require('session-file-store')(sessionExpress);

var secret = 'keyboard cat';
var sessionIdKey = 'connect.sid';

var session = sessionExpress({
    secret: secret,
    store: new FileStore(),
    resave: true,
    saveUninitialized: true,
    cookie: { 
        maxAge: 60 * 60 * 1000
    }
});

// setup servers
var server = http.createServer(app, function (req, res){
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
});

server.listen(8000);

var sio = io(server);
sio.use(function(socket, accept) {        
    // writing sessionId, sent as parameter, on the socket.handshake cookies
    if (socket.handshake.query.sessionId) {
        var cookies = (socket.handshake.headers.cookie || '').split(';');
        cookies.push(sessionIdKey + '=' + socket.handshake.query.sessionId);
        socket.handshake.headers.cookie = cookies.join(';');
    }
    session(socket.handshake, {}, function(err) {
        if (err) return accept(err);
        console.log('User trying to connect to Socket.io');
        var session = socket.handshake.session,
            userData = session.userdata || {};

        // is connected and good
        if (!userData || !userData.connected) {
            console.log('----- User has no active session, error');
            accept(new Error('Not authenticated'));
        } else {
            console.log('----- Socket.io connection attempt successful');
            accept(null, session.userid !== null);
        }
    });
});


sio.on('connection', function (socket) {
    console.log('Connection');
});

client.js

        function getCookie(name) {
            var value = "; " + document.cookie;
            var parts = value.split("; " + name + "=");
            if (parts.length == 2) return decodeURIComponent(parts.pop().split(";").shift());
        }

        function fetch(url, data, callback) {
            try {
                var x = new XMLHttpRequest();
                x.open(data ? 'POST' : 'GET', url, 1);
                x.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
                x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
                x.onreadystatechange = function () {
                    x.readyState > 3 && callback && callback(x.responseText, x);
                };
                x.send(data || null);
            } catch (e) {
                window.console && console.log(e);
            }
        };


        function connectServer(cb) {
            var sessionId = getCookie('connect.sid');
            var data = { forceNew: true, query : {  } };
            if (sessionId) {
                data.query.sessionId = sessionId
            }

            console.log('Trying to connect to Socket.io server');

            var server = io('http://socket.dev:8000', data);
            server.on('error', function (err) {
                console.log('----- Connection error : [%s]', err);
                setTimeout(function () {
                    cb();
                }, 200);
            });
            server.on('connect', function (data) {
                console.log('----- Connection successful with sessionId [%s]', sessionId);
                setTimeout(function () {
                    cb();
                }, 200);
            });
        }

        if (getCookie('connect.sid')) {
            console.log('Session cookie Detected');
            connectServer(function () { });
        } else {
            connectServer(function () {
                console.log('Call ./authenticate to create session server side');
                fetch('./authenticate', null, function () {
                    console.log('Session created')
                    connectServer(function () {});
                }); 
            }); 
        }

Execution

First Page loading Results

首页加载结果

Client :

Trying to connect to Socket.io server
----- Connection error : [Not authenticated]
Call ./authenticate to create session server side
Session created
Trying to connect to Socket.io server
----- Connection successful with sessionId [s:Ir9dVPi8wzplPCoeNXAsDlOkhL8AW0gx.wwzUQ2jftntWEc6lRdYqGxRBoszjPtjT4dBW/KjFIXQ]

Server :

User trying to connect to Socket.io
----- User has no active session, error
User trying to connect to Socket.io
----- Socket.io connection attempt successful
Connection

Reload page

Client :

Session cookie Detected
Trying to connect to Socket.io server
----- Connection successful with sessionId [s:Ir9dVPi8wzplPCoeNXAsDlOkhL8AW0gx.wwzUQ2jftntWEc6lRdYqGxRBoszjPtjT4dBW/KjFIXQ]

Server :

User trying to connect to Socket.io
----- Socket.io connection attempt successful
Connection