socket.io并表达4个会话

Bob*_*ark 10 session node.js express socket.io

我想在我的socket.io应用程序中访问express 4 session.我是Node的新手,我在实现这个功能时遇到了一些麻烦.

我发现了一个允许访问快速4会话的npm模块:https://www.npmjs.org/package/session.socket.io-express4https://github.com/eiriklv/session.socket.io

如果你看下面我的app.js代码,我在做错了session,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;
Run Code Online (Sandbox Code Playgroud)

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

  • 禁用https服务器.
  • cookieParser使用密码短语设置对象(因此它"实际上"将密码短语导出到io = new SessionSockets(serverIO, sessionStore, cookieParser);)
  • 使用最少的cookie选项.

无论如何,我对此有点失落,欢迎任何建议/评论家.


UPDATE

好吧,经过多次尝试后,我想我能搞定它!

问题在于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());
Run Code Online (Sandbox Code Playgroud)

请注意,如果我使用var io = new SessionSockets(serverIO, sessionStore, cookieParser);(而不是cookieParser())则它不起作用.这似乎是个问题.

如果我使用:

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"));
Run Code Online (Sandbox Code Playgroud)

然后模块崩溃并出现以下错误消息:

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

但如果我使用:

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());
Run Code Online (Sandbox Code Playgroud)

一切都很好看.

现在在cookie-parser doc(https://github.com/expressjs/cookie-parser)中,它说你可以传递一个密钥来获取cookie签名.这是我想要的东西.

有人可以解释我与cookie解析器秘密短语和会话秘密短语的关系吗?他们必须是相同/不同的吗?

Sea*_*son 19

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

  • 表达4.2.0
  • socket.io 1.1.0
  • cookie-parser 1.0.1
  • cookie-session 1.0.2

码:

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);
    });
});
Run Code Online (Sandbox Code Playgroud)

然后,您可以从套接字的握手访问会话:

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

对于想知道如何/为何如此工作的人:

  • 我们handshake通过cookie解析器发送请求,以便cookie可用
  • 然后我们发送handshake直通会话中间件,就好像它是一个正常的请求
  • 中间件附加session到请求
  • 我们使用handshake因为所有意图和目的,它是一个普通的请求,解析器和会话中间件可以正确处理它.这就是为什么你必须访问session通过handshake

  • 同样也用于快递会议 (3认同)

xpe*_*int 13

使用新的快速会话中间件,您只需添加IO中间件:

io.use(function(socket, next) {
  session(socket.handshake, {}, next);
});
Run Code Online (Sandbox Code Playgroud)

一个完整的例子如下所示:

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);
});
Run Code Online (Sandbox Code Playgroud)

我创建了一个超级迷你npm包socket.io-express-session,就像我上面解释的那样.


Nat*_*ano 1

这可能适用于 Express 4 / socket.io 1.X 我从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'));
 }
});
Run Code Online (Sandbox Code Playgroud)