带有快速会话的 ReactJS 和 socket.io - 套接字未使用正确的会话并创建了许多其他会话

Posted

技术标签:

【中文标题】带有快速会话的 ReactJS 和 socket.io - 套接字未使用正确的会话并创建了许多其他会话【英文标题】:ReactJS and socket.io with express session - socket not using the right session and creating many others 【发布时间】:2019-03-31 22:55:10 【问题描述】:

我已经尝试了很多方法来获取 Node.JS 中 socket.io 连接中的 express session 变量,但总是失败。我注意到,每当我使用会话中间件时,都没有使用正确的会话,而是创建了 3 个其他无用的会话(除非 saveUninitialized:true,如果为 false,则不会保存它,但它仍然使用了错误的会话)。

我试过了:

使用 cookie 解析器。 在文件中存储会话。 express-socket.io-session。 redis 还有一些我已经记不起来的事情了。

但这一切都归结为一件事 - 套接字不使用与快速请求 (req.session) 相同的会话,而是创建 3 个其他会话,并在套接字活动时继续创建新会话。

App组件内客户端socket.io的设置:

componentWillMount() 
    let socket = io("http://localhost:5000");
    this.setState(socket);
    socket.emit("test"); // This actually returns the correct session.
  

我在 ReactJS 中发送 AJAX 的方式示例:

fetch('http://localhost:5000/home/userinfo', 
  method: 'GET',
  credentials: 'include',
  headers: 
    'Accept': 'application/json',
    'Content-Type': 'application/json',
  ,
).then(function(response) 
  return response.json();
).then(function(data) 
  if (data.login) 
    self.setState(username: data.login);
  
  else 
    self.props.history.push("/login");
  
);

快速会话设置:

var sessionMiddleware = session(
  store: new sessionFileStore( path: './sessions' ),
  secret: 'nothingspecial',
  maxAge: new Date(Date.now() + 3600000),
  resave: true,
  saveUninitialized: false
);
app.use(sessionMiddleware);

socket.io 连接:

const server = app.listen(port, () => console.log(`Listening on port $port`));

const io = require('socket.io').listen(server);
io.use(function(socket, next) 
  sessionMiddleware(socket.handshake, , next); 
);
io.on('connection', function(socket) 
  console.log('a user connected');
  socket.on('disconnect', function() 
    console.log('user disconnected');
  );
  socket.on('test', function() 
    console.log(socket.handshake.session);
    // Returns different session than when using app.get and then req.session for example
  );
);

还有一些其他 app.use 可能值得在这里发布:

app.use(bodyParser.json());
app.use(bodyParser.urlencoded( extended: false ));
app.use(function (req, res, next) 
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
  res.setHeader('Access-Control-Allow-Credentials', true);
  next();
);

非常感谢您的帮助,因为我已经浪费了很多时间试图弄清楚这一点。

编辑:我注意到,当我直接从连接开始的位置(应用程序组件)socket.emit 刷新页面时,它实际上抓住了正确的会话。 我尝试在 App 组件中创建一些函数,但是当我将函数传递给不同的组件并运行 props 函数时,它仍然会创建一个新会话。

我如何通过套接字:

<Route path="/home" render=(props) => <Home ...props socket=this.state.socket /> />

【问题讨论】:

【参考方案1】:

我决定从 socket.io 切换到标准 WebSocket(ws),这似乎也更适合我的需求。使用 ws 共享会话非常有效,您只需要在设置会话变量后强制刷新页面即可。

这有助于: ExpressJS & Websocket & session sharing

还要记住,再也没有 req.upgradeReq 这样的东西了。 req 像这样在 wss.connection 上传递:

wss.on('connection', function(ws, req) 
//req.upgradeReq = req;
);

【讨论】:

以上是关于带有快速会话的 ReactJS 和 socket.io - 套接字未使用正确的会话并创建了许多其他会话的主要内容,如果未能解决你的问题,请参考以下文章

使用快速会话的套接字 IO - socket.request.res 未定义

带有 SPA 应用程序和 API 的会话

带有快速生成器的 socket.io

带有 PHP 应用程序和用户会话的 NodeJS

在不同服务器上的 ReactJS 和 WIX Web 应用程序之间共享会话

socket.io 和 reactjs 实现即时通讯