98

我正在使用快递框架。我想从 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
    }); 
});
4

11 回答 11

67

这不适用于通过 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!!!!
    });
  }
});

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

于 2011-01-21T03:18:12.297 回答
34

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

请改为检查此解决方案(对于 Socket.IO >= v0.7)。请参阅此处的文档。

于 2011-08-11T14:30:42.100 回答
8

我建议不要完全重新发明轮子。你需要的工具已经是一个 npm 包。我想这就是你需要的:session.socket.io 我这几天正在使用它,我想它会很有帮助的!!将 express-session 链接到 socket.io 层会有很多好处!

于 2014-01-15T16:52:44.713 回答
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,使用该redis-connect库。

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

希望这可以帮助在搜索谷歌时找到这篇文章的人(就像我一样;)

于 2011-05-30T02:32:09.707 回答
2

看到这个:Socket.IO Authentication

我建议不要通过client.request...client.listener...不直接附加到client对象上获取任何内容,并且始终指向最后登录的用户!

于 2011-01-24T16:33:40.647 回答
2

对于未来的读者 - 有一种优雅而简单的方法可以使用 express-session 访问 socket.io 中的会话。来自 socket.io 文档:

大多数现有的 Express 中间件模块应该与 Socket.IO 兼容,您只需要一个小包装函数来使方法签名匹配:

 const wrap = middleware => (socket, next) => middleware(socket.request, {}, next);

结束请求-响应周期并且不调用 next() 的中间件函数将不起作用。

快速会话示例:

const session = require("express-session");
io.use(wrap(session({ secret: "cats" })));
io.on("connection", (socket) => {
   const session = socket.request.session; // here you get access to the session :)
});
 
于 2021-02-16T21:29:06.330 回答
1

查看Socket.IO-connect

围绕 Socket.IO-node 连接 WebSocket 中间件包装器 https://github.com/bnoguchi/Socket.IO-connect

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

于 2011-09-05T16:01:53.670 回答
1

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

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

于 2012-01-12T10:28:29.913 回答
1

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

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

为我工作!!

于 2017-11-29T04:04:17.753 回答
0

你可以看看这个:https ://github.com/bmeck/session-web-sockets

或者您可以使用:

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

希望这可以帮助。

于 2011-01-12T04:53:27.433 回答
0

截至 2022 年 2 月,Socket.IO v4 支持此功能:

https://socket.io/docs/v4/faq/#usage-with-express-session

const express = require('express');
const session = require('express-session');
const app = express();

const server = require('http').createServer(app);
const io = require('socket.io')(server);

const sessionMiddleware = session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }});
// register middleware in Express
app.use(sessionMiddleware);
// register middleware in Socket.IO
io.use((socket, next) => {
  sessionMiddleware(socket.request, {}, next);
  // sessionMiddleware(socket.request, socket.request.res, next); will not work with websocket-only
  // connections, as 'socket.request.res' will be undefined in that case
});

io.on('connection', (socket) => {
  const session = socket.request.session;
  session.connections++;
  session.save();
});

const port = process.env.PORT || 3000;
server.listen(port, () => console.log('server listening on port ' + port));
于 2022-02-28T00:28:55.473 回答