套接字。io和express 4个会议

时间:2022-08-22 15:26:22

I would like to access the express 4 session in my socket.io app. I'm kind of new with Node and I have some troubles implementing this functionality.

我想要进入我的插座中的特快4会议。io app。我是Node的新手,在实现这个功能时遇到了一些麻烦。

I found a npm module that allows access to the express 4 session : https://www.npmjs.org/package/session.socket.io-express4 or https://github.com/eiriklv/session.socket.io

我找到了一个允许访问express4会话的npm模块:https://www.npmjs.org/package/session.socket.io-express4或https://github.com/eiriklv/session.socket.io

If you look at my app.js code below, I'm doing something wrong in the session, sessionStore or cookieParser setup because I just can't get this module working.

如果您看一下下面的app.js代码,我在会话、sessionStore或cookieParser设置中犯了一些错误,因为我无法让这个模块工作。

// init modules
var express = require('express');
var helmet = require('helmet');
var fs = require('fs');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var memoryStore = session.MemoryStore;
var app = express();

// set variables
var options = {
  key: fs.readFileSync('./openssl_keys/server_key.pem'),
  cert: fs.readFileSync('./openssl_keys/server_cert.pem')
};
var cookieSecret = "secret phrase";
var sessionStore = new memoryStore();

app.set('env', process.env.NODE_ENV || 'development');

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser(cookieSecret));
app.use(session({
    secret: cookieSecret,
    cookie: {httpOnly: true, secure: true},
    store: sessionStore
}));
app.use(function(req, res, next){
    res.locals.session = req.session;
    next();

});
app.use(express.static(path.join(__dirname, 'public')));

//routes
require('./routes/index')(app);
require('./routes/test')(app);


// starting http and https servers
var http = require('http').createServer(app).listen(8000, function(){
    console.log("http server listening on port 8000");
});
var https = require('https').createServer(options, app).listen(8080, function(){
    console.log("https server listening on port 8080"); 
});

// starting socket.io & session handler
var serverIO = require('socket.io').listen(https);
var SessionSockets  = require('session.socket.io-express4');
var io = new SessionSockets(serverIO, sessionStore, cookieParser);

io.on('connection', function(err, socket, session){
    if(err) throw err;
    console.log("connected");
    //console.log(session);
    socket.on('clientMessage', function(content) {
        console.log("received client message")
        console.log(content);
    });

});

module.exports = app;

I tried multiples possibilities like :

我尝试了多种可能性,比如:

  • Disabling https server.
  • 禁用https服务器。
  • Setting up a cookieParser object with secret phrase (so it "actually" exports the secret phrase to io = new SessionSockets(serverIO, sessionStore, cookieParser);)
  • 使用秘密短语设置cookieParser对象(因此它“实际上”将秘密短语导出到io = new SessionSockets(serverIO、sessionStore、cookieParser);
  • Using minimal cookie options.
  • 使用最少的饼干选项。

Anyway I'm a bit lost with this, any suggestions/critics are welcome.

不管怎样,我有点迷失了方向,任何建议/批评都是受欢迎的。


UPDATE

更新

Ok so after numerous tries I think I could get it work!

好吧,在无数次尝试之后,我想我能把它做好!

The problem is with the cookieParser initialization which the correct way seems to be :

问题是对cookieParser初始化的正确方式是:

var cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use(session({
    secret: "secret phrase",
    cookie: {httpOnly: true, secure: true},
    store: sessionStore
}));
var io = new SessionSockets(serverIO, sessionStore, cookieParser());

Notice that if I use var io = new SessionSockets(serverIO, sessionStore, cookieParser); (instead of cookieParser()) then it ain't working. That seems to be the problem.

注意,如果我使用var io = new SessionSockets(serverIO, sessionStore, cookieParser);(而不是cookieParser(),那么它就不能工作了。这似乎是问题所在。

If I use :

如果我使用:

app.use(cookieParser("secret phrase"));
app.use(session({
    secret: "secret phrase",
    cookie: {httpOnly: true, secure: true},
    store: sessionStore
}));
var io = new SessionSockets(serverIO, sessionStore, cookieParser("secret phrase"));

then the module crashes with the following error message :

然后模块崩溃,错误信息如下:

session.socket.io-express4/session.socket.io.js:41
ake.signedCookies[key] = handshake.signedCookies[key].match(/\:(.*)\./).pop();
                                                                        ^
TypeError: Cannot call method 'pop' of null

But if I use :

但是如果我使用:

app.use(cookieParser("secret phrase"));
app.use(session({
    secret: "secret phrase",
    cookie: {httpOnly: true, secure: true},
    store: sessionStore
}));
var io = new SessionSockets(serverIO, sessionStore, cookieParser());

Then everything looks fine.

然后一切都看起来好。

Now in the cookie-parser doc (https://github.com/expressjs/cookie-parser) it's saying you can pass a secret key to get the cookies signed. Which is something I'd like to have.

现在,在cookie-parser doc (https://github.com/expressjs/cookie-parser)中,它表示可以传递一个密匙来让cookie签名。这是我想要的。

Could someone explain me the relation with the cookie-parser secret phrase and the session secret phrase ? Do they have to be the same/different ?

有人能解释一下cookie-parser秘密短语和会话秘密短语的关系吗?它们一定要相同/不同吗?

7 个解决方案

#1


20  

Here's my solution for the following environment:

以下是我对以下环境的解决方案:

  • express 4.2.0
  • 表达4.2.0
  • socket.io 1.1.0
  • 套接字。io 1.1.0
  • cookie-parser 1.0.1
  • cookie-parser 1.0.1
  • cookie-session 1.0.2
  • cookie会话1.0.2

Code:

代码:

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);
    });
});

Then you can access the session from the socket's handshake:

然后您可以从插座的握手访问会话:

io.on('connection', function (socket) {
    console.log("Session: ", socket.handshake.session);
});

For people wondering how/why this works:

对于想知道为什么这样做的人:

  • We send the handshake request through the cookie parser so that cookies are available
  • 我们通过cookie解析器发送握手请求,以便cookie可用
  • Then we send the handshake through session middleware as if its a normal request
  • 然后我们通过会话中间件发送握手,就好像它是一个普通的请求一样
  • The middleware attaches session to the request
  • 中间件将会话附加到请求
  • We use handshake because for all intents and purposes, it is a normal request, and the parser and session middleware can deal with it properly. This is why you must access the session through the handshake
  • 我们使用握手是因为对于所有的意图和目的来说,它是一个普通的请求,解析器和会话中间件可以正确地处理它。这就是为什么您必须通过握手访问会话。

#2


10  

With the new express-session middleware all you have to do is to add the IO middleware:

使用新的express-session中间件,您只需添加IO中间件:

io.use(function(socket, next) {
  session(socket.handshake, {}, next);
});

A complete example would look like this:

完整的例子如下:

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

var Session = require('express-session'),
    SessionStore = require('session-file-store')(Session);
    session = Session({
      store: new SessionStore({ path: './tmp/sessions' }),
      secret: 'pass',
      resave: true,
      saveUninitialized: true
    });

io.use(function(socket, next) {
  session(socket.handshake, {}, next);
});

io.on('connection', function(socket){
  console.log('a user connected');
  socket.emit('chat message', "UserID: " + socket.handshake.session.uid);
});

I created a super mini npm package socket.io-express-session which works as I explained above.

我创建了一个超级迷你npm包套接字。io-express-session,如我上面解释的那样。

#3


2  

This worked for me with

这对我很有效

  • express 4.9.0
  • 表达4.9.0
  • express.io 1.1.13
  • 表达。io 1.1.13
  • connect-redis 2.1.0
  • connect-redis魅惑
  • express-session 1.8.2
  • express-session 1.8.2

What I wanted was to share sessions with a frontend and backend API through redis. Separate machines, sharing same DB. Sessions are created and users logged in when they open page on the frontend, then the api looks up the logged in users on requests.

我想通过redis与前端和后端API共享会话。分开的机器,共享相同的DB。当用户在前台打开页面时,将创建会话并登录,然后api在请求中查找登录的用户。

var cookieParser = require('cookie-parser')();
var session = require('express-session');
var RedisStore = require('connect-redis')(session);

var db = require('./db')(config);

var sessionStore = session( {
        store: new RedisStore({ client: db }),
        secret: SECRET,
        cookie: { secure: false }
    }
);

app.use(cookieParser);
app.use(sessionStore);

// attach sessions to pure websocket requests
app.io.use(function(req, next) {
    var res = {};
    cookieParser(req, res, function(err) {
        if (err) { return next(err); }
        sessionStore(req, res, next);
    });
});

Note: I set the cookie.secure to false so I can test without https locally.

注意:我设置了cookie。确保为false,这样我就可以在本地不使用https进行测试。

#4


1  

This may work express 4 / socket.io 1.X I grabbed this code form https://github.com/turbonetix/bus.io/blob/master/demo/chat/app.js

这可以用特快4 /插座。io 1。我抓取了这个代码https://github.com/turbonetix/bus.io/blob/master/demo/chat/app.js

io.use(function (socket, next) {
 var handshake = socket.handshake;
  if (handshake.headers.cookie) {
  cookieParser()(handshake, {}, function (err) {
  handshake.sessionID = connect.utils.parseSignedCookie(handshake.cookies[config.session.key], config.session.secret);
    handshake.sessionStore = config.session.store;
    handshake.sessionStore.get(handshake.sessionID, function (err, data) {
      if (err) return next(err);
      if (!data) return next(new Error('Invalid Session'));
      handshake.session = new session.Session(handshake, data);
      next();
    });
   });
 }
 else {
  next(new Error('Missing Cookies'));
 }
});

#5


1  

express 4.13.4 / socket.io 1.4.5

表达4.13.4 /套接字。io 1.4.5

I browse all solutions and modules, but them all not working in my app. Finaly -

我浏览了所有的解决方案和模块,但是它们都不能在我的应用中使用

app.use(session({

      secret: COOKIE_SECRET,
      resave: true,
      saveUninitialized: true,
      store:sessionStore,
      cookie: { domain: 'localhost',secure: false } 

}));  


io.use(function(socket, next) {
                          session({
                              secret: COOKIE_SECRET,
                              resave: true,
                              saveUninitialized: true,
                              store:sessionStore,
                              cookie: { domain: 'localhost',secure: false } 
                          })(socket.handshake, {}, next);
});

working like a charm.

工作就像一个魅力。

#6


0  

it gave me a hard time to find the right solution. Here is what works for me :

我很难找到正确的解决办法。以下是对我有效的方法:

/*

    Just to see, before my code : 

    var sessionStore = new mongoStore({
        db: db.connection.db,
        collection: config.sessionCollection
    });

    app.use(session({
        secret: config.sessionSecret,
        store: sessionStore
    }));

*/

io.use(function(socket, next) {

    var handshake = socket.handshake;

    if (handshake.headers.cookie) {

        cookieParser(config.sessionSecret)(handshake, {}, function(err) {

            handshake.sessionID = handshake.signedCookies['connect.sid']; // <- 'connect.sid' > your key could be different, but this is the default 
            handshake.sessionStore = sessionStore;

            handshake.sessionStore.get(handshake.sessionID, function(err, data) {

                if (err) return next(err);

                if (!data) return next(new Error('Invalid Session'));

                handshake.session = new session.Session(handshake, data);
                next();
            });
        });

    } else {

        next(new Error('Missing Cookies'));
    }
});

express 4.2.0 / socket.io 1.0.6

表达4.2.0 /套接字。io 1.0.6

#7


0  

express-socket.io-session is a ready-made solution for your problem. Normally the session created at socket.io end has different sid than the ones created in express.js

express-socket。会话是您的问题的现成解决方案。通常是在socket中创建的会话。io端与在express.js中创建的sid不同。

Before knowing that fact, when I was working through it to find the solution, I found something a bit weird. The sessions created from express.js instance were accessible at the socket.io end, but the same was not possible for the opposite. And soon I came to know that I have to work my way through managing sid to resolve that problem. But, there was already a package written to tackle such issue. It's well documented and gets the job done. Hope it helps

在知道这个事实之前,当我通过它来寻找解决方案时,我发现了一些奇怪的东西。由express创建的会话。在套接字中可以访问js实例。io结束了,但是同样的事情不可能发生在相反的事情上。很快我就意识到我必须通过管理sid来解决这个问题。但是,已经有了一个解决这类问题的方案。它有很好的文档,并且完成了工作。希望它能帮助

#1


20  

Here's my solution for the following environment:

以下是我对以下环境的解决方案:

  • express 4.2.0
  • 表达4.2.0
  • socket.io 1.1.0
  • 套接字。io 1.1.0
  • cookie-parser 1.0.1
  • cookie-parser 1.0.1
  • cookie-session 1.0.2
  • cookie会话1.0.2

Code:

代码:

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);
    });
});

Then you can access the session from the socket's handshake:

然后您可以从插座的握手访问会话:

io.on('connection', function (socket) {
    console.log("Session: ", socket.handshake.session);
});

For people wondering how/why this works:

对于想知道为什么这样做的人:

  • We send the handshake request through the cookie parser so that cookies are available
  • 我们通过cookie解析器发送握手请求,以便cookie可用
  • Then we send the handshake through session middleware as if its a normal request
  • 然后我们通过会话中间件发送握手,就好像它是一个普通的请求一样
  • The middleware attaches session to the request
  • 中间件将会话附加到请求
  • We use handshake because for all intents and purposes, it is a normal request, and the parser and session middleware can deal with it properly. This is why you must access the session through the handshake
  • 我们使用握手是因为对于所有的意图和目的来说,它是一个普通的请求,解析器和会话中间件可以正确地处理它。这就是为什么您必须通过握手访问会话。

#2


10  

With the new express-session middleware all you have to do is to add the IO middleware:

使用新的express-session中间件,您只需添加IO中间件:

io.use(function(socket, next) {
  session(socket.handshake, {}, next);
});

A complete example would look like this:

完整的例子如下:

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

var Session = require('express-session'),
    SessionStore = require('session-file-store')(Session);
    session = Session({
      store: new SessionStore({ path: './tmp/sessions' }),
      secret: 'pass',
      resave: true,
      saveUninitialized: true
    });

io.use(function(socket, next) {
  session(socket.handshake, {}, next);
});

io.on('connection', function(socket){
  console.log('a user connected');
  socket.emit('chat message', "UserID: " + socket.handshake.session.uid);
});

I created a super mini npm package socket.io-express-session which works as I explained above.

我创建了一个超级迷你npm包套接字。io-express-session,如我上面解释的那样。

#3


2  

This worked for me with

这对我很有效

  • express 4.9.0
  • 表达4.9.0
  • express.io 1.1.13
  • 表达。io 1.1.13
  • connect-redis 2.1.0
  • connect-redis魅惑
  • express-session 1.8.2
  • express-session 1.8.2

What I wanted was to share sessions with a frontend and backend API through redis. Separate machines, sharing same DB. Sessions are created and users logged in when they open page on the frontend, then the api looks up the logged in users on requests.

我想通过redis与前端和后端API共享会话。分开的机器,共享相同的DB。当用户在前台打开页面时,将创建会话并登录,然后api在请求中查找登录的用户。

var cookieParser = require('cookie-parser')();
var session = require('express-session');
var RedisStore = require('connect-redis')(session);

var db = require('./db')(config);

var sessionStore = session( {
        store: new RedisStore({ client: db }),
        secret: SECRET,
        cookie: { secure: false }
    }
);

app.use(cookieParser);
app.use(sessionStore);

// attach sessions to pure websocket requests
app.io.use(function(req, next) {
    var res = {};
    cookieParser(req, res, function(err) {
        if (err) { return next(err); }
        sessionStore(req, res, next);
    });
});

Note: I set the cookie.secure to false so I can test without https locally.

注意:我设置了cookie。确保为false,这样我就可以在本地不使用https进行测试。

#4


1  

This may work express 4 / socket.io 1.X I grabbed this code form https://github.com/turbonetix/bus.io/blob/master/demo/chat/app.js

这可以用特快4 /插座。io 1。我抓取了这个代码https://github.com/turbonetix/bus.io/blob/master/demo/chat/app.js

io.use(function (socket, next) {
 var handshake = socket.handshake;
  if (handshake.headers.cookie) {
  cookieParser()(handshake, {}, function (err) {
  handshake.sessionID = connect.utils.parseSignedCookie(handshake.cookies[config.session.key], config.session.secret);
    handshake.sessionStore = config.session.store;
    handshake.sessionStore.get(handshake.sessionID, function (err, data) {
      if (err) return next(err);
      if (!data) return next(new Error('Invalid Session'));
      handshake.session = new session.Session(handshake, data);
      next();
    });
   });
 }
 else {
  next(new Error('Missing Cookies'));
 }
});

#5


1  

express 4.13.4 / socket.io 1.4.5

表达4.13.4 /套接字。io 1.4.5

I browse all solutions and modules, but them all not working in my app. Finaly -

我浏览了所有的解决方案和模块,但是它们都不能在我的应用中使用

app.use(session({

      secret: COOKIE_SECRET,
      resave: true,
      saveUninitialized: true,
      store:sessionStore,
      cookie: { domain: 'localhost',secure: false } 

}));  


io.use(function(socket, next) {
                          session({
                              secret: COOKIE_SECRET,
                              resave: true,
                              saveUninitialized: true,
                              store:sessionStore,
                              cookie: { domain: 'localhost',secure: false } 
                          })(socket.handshake, {}, next);
});

working like a charm.

工作就像一个魅力。

#6


0  

it gave me a hard time to find the right solution. Here is what works for me :

我很难找到正确的解决办法。以下是对我有效的方法:

/*

    Just to see, before my code : 

    var sessionStore = new mongoStore({
        db: db.connection.db,
        collection: config.sessionCollection
    });

    app.use(session({
        secret: config.sessionSecret,
        store: sessionStore
    }));

*/

io.use(function(socket, next) {

    var handshake = socket.handshake;

    if (handshake.headers.cookie) {

        cookieParser(config.sessionSecret)(handshake, {}, function(err) {

            handshake.sessionID = handshake.signedCookies['connect.sid']; // <- 'connect.sid' > your key could be different, but this is the default 
            handshake.sessionStore = sessionStore;

            handshake.sessionStore.get(handshake.sessionID, function(err, data) {

                if (err) return next(err);

                if (!data) return next(new Error('Invalid Session'));

                handshake.session = new session.Session(handshake, data);
                next();
            });
        });

    } else {

        next(new Error('Missing Cookies'));
    }
});

express 4.2.0 / socket.io 1.0.6

表达4.2.0 /套接字。io 1.0.6

#7


0  

express-socket.io-session is a ready-made solution for your problem. Normally the session created at socket.io end has different sid than the ones created in express.js

express-socket。会话是您的问题的现成解决方案。通常是在socket中创建的会话。io端与在express.js中创建的sid不同。

Before knowing that fact, when I was working through it to find the solution, I found something a bit weird. The sessions created from express.js instance were accessible at the socket.io end, but the same was not possible for the opposite. And soon I came to know that I have to work my way through managing sid to resolve that problem. But, there was already a package written to tackle such issue. It's well documented and gets the job done. Hope it helps

在知道这个事实之前,当我通过它来寻找解决方案时,我发现了一些奇怪的东西。由express创建的会话。在套接字中可以访问js实例。io结束了,但是同样的事情不可能发生在相反的事情上。很快我就意识到我必须通过管理sid来解决这个问题。但是,已经有了一个解决这类问题的方案。它有很好的文档,并且完成了工作。希望它能帮助