node.js socket.io 和 express 4 个会话
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23494016/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
socket.io and express 4 sessions
提问by Bobby Shark
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.
我想在我的 socket.io 应用程序中访问 express 4 会话。我对 Node 有点陌生,在实现此功能时遇到了一些麻烦。
I found a npm module that allows access to the express 4 session : https://www.npmjs.org/package/session.socket.io-express4or https://github.com/eiriklv/session.socket.io
我找到了一个允许访问 express 4 会话的 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, sessionStoreor cookieParsersetup because I just can't get this module working.
如果你看看我下面的 app.js 代码,我在session,sessionStore或cookieParsersetup 中做错了,因为我无法让这个模块工作。
// 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
httpsserver. - Setting up a
cookieParserobject with secret phrase (so it "actually" exports the secret phrase toio = new SessionSockets(serverIO, sessionStore, cookieParser);) - Using minimal
cookieoptions.
- 禁用
https服务器。 cookieParser使用秘密短语设置对象(因此它“实际上”将秘密短语导出到io = new SessionSockets(serverIO, sessionStore, cookieParser);)- 使用最少的
cookie选项。
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 文档 ( 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 秘密短语和会话秘密短语的关系吗?它们必须相同/不同吗?
回答by Sean Adkinson
Here's my solution for the following environment:
这是我针对以下环境的解决方案:
- express 4.2.0
- socket.io 1.1.0
- cookie-parser 1.0.1
- cookie-session 1.0.2
- 快递 4.2.0
- socket.io 1.1.0
- cookie 解析器 1.0.1
- 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
handshakerequest through the cookie parser so that cookies are available - Then we send the
handshakethrough session middleware as if its a normal request - The middleware attaches
sessionto the request - We use
handshakebecause 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 thesessionthrough thehandshake
- 我们
handshake通过 cookie 解析器发送请求,以便 cookie 可用 - 然后我们发送
handshakethrough session 中间件,就好像它是一个正常的请求一样 - 中间件附加
session到请求 - 我们使用
handshake是因为出于所有意图和目的,它是一个正常的请求,解析器和会话中间件可以正确处理它。这就是为什么您必须session通过handshake
回答by xpepermint
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-sessionwhich works as I explained above.
我创建了一个超级迷你 npm 包socket.io-express-session,它的工作原理如我上面所解释的。
回答by Eivind
This worked for me with
这对我有用
- express 4.9.0
- express.io 1.1.13
- connect-redis 2.1.0
- express-session 1.8.2
- 快递 4.9.0
- express.io 1.1.13
- 连接-redis 2.1.0
- 快速会话 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 共享会话。不同的机器,共享同一个数据库。当用户在前端打开页面时,会话被创建并且用户登录,然后 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 falseso I can test without https locally.
注意:我将 cookie.secure 设置为false,因此我可以在没有 https 的情况下进行本地测试。
回答by xbtc
express 4.13.4/ socket.io 1.4.5
快递4.13.4/ socket.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.
像魅力一样工作。
回答by Nathan Romano
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
这可能适用于 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'));
}
});
回答by Peter V
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 / socket.io 1.0.6
回答by Rahil051
express-socket.io-sessionis 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.io-session是针对您的问题的现成解决方案。通常在 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 实例创建的会话可以在 socket.io 端访问,但相反的情况则不可能。很快我就知道我必须通过管理 sid 来解决这个问题。但是,已经有一个包可以解决这个问题。它有据可查,可以完成工作。希望能帮助到你

