socket.io并表示4个会话

我想在我的socket.io应用程序中访问express 4会话。 我有点新的Node,我有一些麻烦实施这个function。

我发现一个npm模块,可以访问express 4会话: https : //www.npmjs.org/package/session.socket.io-express4或https://github.com/eiriklv/session.socket.io

如果你看下面我的app.js代码,我会在sessionsessionStore或者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; 

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

  • 禁用https服务器。
  • 使用秘密短语设置cookieParser对象(所以它“实际”将密码输出到io = new SessionSockets(serverIO, sessionStore, cookieParser);
  • 使用最小的cookie选项。

无论如何,我有点失落,欢迎任何build议/评论家。


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

注意,如果我使用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")); 

那么该模块会崩溃,并显示以下错误消息:

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

但是,如果我使用:

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

然后一切都很好。

现在在cookieparsing器文档( https://github.com/expressjs/cookie-parser )它是说你可以通过一个秘密密钥来获得签名的cookie。 这是我想要的东西。

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

这是我对以下环境的解决scheme:

  • expression4.2.0
  • socket.io 1.1.0
  • cookieparsing器1.0.1
  • cookie会话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); }); }); 

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

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

对于想知道如何/为什么这样工作的人:

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

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

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

一个完整的例子看起来像这样:

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

我创build了一个超级迷你npm包socket.io-express-session ,其工作方式如上所述。

这对我工作

  • expression4.9.0
  • express.io 1.1.13
  • connect-redis 2.1.0
  • 快速会话1.8.2

我想要的是通过redis与前端和后端API共享会话。 分开的机器,共享相同的DB。 创build会话并在用户打开前端页面时login,然后api根据请求查找已login的用户。

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

注意 :我将cookie.secure设置为false,因此我可以在本地不使用https的情况下进行testing。

这可能工作expression4 / socket.io 1.X我抓住了这个代码的formshttps://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')); } }); 

这让我很难find正确的解决scheme。 这是对我有用的东西:

 /* 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')); } }); 

表示4.2.0 / socket.io 1.0.6

express-socket.io-session是针对您的问题的现成解决scheme。 通常,在socket.io结尾创build的会话与在express.js中创build的会话不同

在知道这个事实之前,当我正在通过它来寻找解决scheme时,我发现有些奇怪。 从express.js实例创build的会话可以在socket.io端访问,但是相反,这是不可能的。 很快,我开始知道必须通过pipe理sid来解决这个问题。 但是,已经有一个解决这个问题的scheme了。 这是有据可查的,并完成工作。 希望能帮助到你

表示4.13.4 / socket.io 1.4.5

我浏览所有的解决scheme和模块,但他们都不在我的应用程序工作。 最后 –

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

像魅力一样工作。