socket.io和会话?


95

我正在使用快速框架。我想从socket.io访问会话数据。我尝试使用client.listener.server.dynamicViewHelpers数据来表达dynamicHelpers,但是我无法获取会话数据。有没有简单的方法可以做到这一点?请看代码

app.listen(3000);

var io = require('socket.io');
var io = io.listen(app);

io.on('connection', function(client){
    // I want to use session data here
    client.on('message', function(message){
        // or here
    });
    client.on('disconnect', function(){
        // or here
    }); 
});

5
或者可以使用此非常好的
Fabiano Soriani 2011年

3
@FabianoPS-不再起作用-connect不再提供其依赖的parseCookie方法。
2012年

1
@UpTheCreek-由于connect不再使用parseCookie方法,这怎么可能?
2012年

@Aust-好问题,我不知道现在最好的方法是什么。这真是一个烂摊子。烦人的是,大多数解决方法的讨论也都在socket.io上进行了讨论(并非所有人都在使用socket.io!)。现在有一个parseSignedCookie函数,但这也是私有的,因此也有打破更改的风险。
2012年

2
:对于Socket.IO(1.x中)和快速(4.x版)的新版本检查这太问题stackoverflow.com/questions/25532692/...
pootzko

Answers:


68

这不适用于通过flashsocket传输的套接字(它不会向服务器发送所需的cookie),但可以可靠地用于其他所有事务。我只是在代码中禁用了flashsocket传输。

为了使其工作,在Express / Connect端,我明确定义了会话存储,以便可以在套接字内使用它:

MemoryStore = require('connect/middleware/session/memory'),
var session_store = new MemoryStore();
app.configure(function () {
  app.use(express.session({ store: session_store }));
});

然后,在我的套接字代码中,包括连接框架,以便可以使用其cookie解析来从cookie中检索connect.sid。然后,我在具有该connect.sid的会话存储中查找会话,如下所示:

var connect = require('connect');
io.on('connection', function(socket_client) {
  var cookie_string = socket_client.request.headers.cookie;
  var parsed_cookies = connect.utils.parseCookie(cookie_string);
  var connect_sid = parsed_cookies['connect.sid'];
  if (connect_sid) {
    session_store.get(connect_sid, function (error, session) {
      //HOORAY NOW YOU'VE GOT THE SESSION OBJECT!!!!
    });
  }
});

然后,您可以根据需要使用会话。


3
它看起来像socket_client.request已socket.io节点的最新版本被删除
美术

6
当心...现在有新的约定可以执行此操作...我建议改用Socket.IO身份验证。参见@Jeffer
BMiner 2011年

2
不幸的是,这将不再起作用-parseCookie不再是connect utils的一部分。显然,它从来都不是公共API的一部分。有一个凌乱的选择- parseSignedCookie,而这也是私有的,所以我面临失传的危机猜测它太..
UpTheCreek

现在,我正在考虑...。为什么不将Cookie的存储区和套接字的存储区设置为同一存储区?
詹姆斯,

34

Socket.IO-sessions模块解决方案通过在客户端(脚本)级别公开会话ID,使应用程序遭受XSS攻击。

请改用此解决方案(对于Socket.IO> = v0.7)。在这里查看文档。


1
@Jeffer-第二种解决方案将无法与当前版本的connect一起使用。
UpTheCreek

2
-1 socket.io是公开会话ID的内容,而不是该模块。没什么大不了的,因为会话ID无论如何都在客户端存储在cookie中...而且该教程不适用于最新版本的Express。
2013年

1
您的解决方案链接只是重定向到socket.iogithub页面..?
TJ


4

编辑:在尝试了一些不起作用的模块之后,我实际上已经走了,并编写了自己的库来执行此操作。无耻的插件:前往https://github.com/aviddiviner/Socket.IO-sessions进行检查。我出于历史目的将旧帖子留在下面:


按照上面pr0zac的解决方案,我无需绕过flashsocket传输就可以很整洁地完成此工作。我也在Socket.IO中使用express。这是如何做。

首先,将会话ID传递给视图:

app.get('/', function(req,res){
  res.render('index.ejs', {
    locals: { 
      connect_sid: req.sessionID
      // ...
    }
  });
});

然后在您的视图中,将其与Socket.IO客户端链接:

<script>
  var sid = '<%= connect_sid %>';
  var socket = new io.Socket();
  socket.connect();
</script>
<input type="button" value="Ping" onclick="socket.send({sid:sid, msg:'ping'});"/>

然后在服务器端Socket.IO侦听器中,将其拾取并读取/写入会话数据:

var socket = io.listen(app);
socket.on('connection', function(client){
  client.on('message', function(message){
    session_store.get(message.sid, function(error, session){
      session.pings = session.pings + 1 || 1;
      client.send("You have made " + session.pings + " pings.");
      session_store.set(message.sid, session);  // Save the session
    });
  });
});

就我而言,我session_store是使用该redis-connect库的Redis 。

var RedisStore = require('connect-redis');
var session_store = new RedisStore;
// ...
app.use(express.session({ store: session_store }));

希望这对在搜索Google时找到此帖子的人有所帮助(就像我一样;)


8
从安全的角度来看,
将会话

4
当会话ID已存储在本地cookie中时,为什么将会话ID放在HTML中这么不好?
加文2014年

3
因为当设置为HttpOnly cookie时无法从javascript访问cookie。通过将session.sid放入HTML中,可以使攻击者获得DOM中所需的一切。
罗沙尔,2015年


2

Socket.IO-connect

在Socket.IO节点周围连接WebSocket中间件包装器 https://github.com/bnoguchi/Socket.IO-connect

这将允许您在使用Socket.IO事件处理程序处理Socket.IO请求之前,将Socket.IO请求向下推送到Express / Connect中间件堆栈,从而可以访问会话,Cookie等。虽然,我不确定它是否可以与所有Socket.IO的传输一起使用。


不幸的是,该模块仍在使用
v0.6

2

您可以使用express-socket.io-session

与socket.io共享基于cookie的快速会话中间件。适用于express> 4.0.0和socket.io> 1.0.0,并且不会向后兼容。

为我工作!


嘿。您将如何在前端使用会话值?我在npm文档中看不到它们。
哈里拉姆

1

您可以看一下:https : //github.com/bmeck/session-web-sockets

或者,您可以使用:

io.on('connection', function(client) { 
  var session = client.listener.server.viewHelpers; 
  // use session here 
});

希望这可以帮助。


我知道会话Web套接字,但是我不想为此使用库,我正在寻找一个简单的解决方案。我尝试了client.listener.server.viewHelpers; {}:但它返回此
SFS

2
尽管起初似乎可行,但这会导致比赛条件。我建议您完全避免。
Shripad Krishna 2011年

1

我不确定我做对了。 https://github.com/LearnBoost/socket.io/wiki/Authorizing

使用握手数据,您可以访问cookie。在cookie中,您可以获取connect.sid,这是每个客户端的会话ID。然后使用connect.sid从数据库获取会话数据(我假设您正在使用RedisStore)


这正是要走的路,但是您并不酷,因此您无法获得堆栈溢出点。github.com/tcr/socket.io-sessiongithub.com/functioncallback/session.socket.io我喜欢第一个更好的清洁器。第二个文件记录得更好。
詹姆斯,

@TJ对此感到抱歉,但是您是否知道答案是2年前?而且它可能不会现在的工作
谭阮

@TanNguyen我知道,这就是为什么我通知你,让你可以不必更新的答案不是指向人的死链接
TJ

@TJ谢谢你。不幸的是,由于两年前的性能问题,我离开了socket.io。因此,我不知道什么是会议socket.io应对当前的方式
谭阮
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.