You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么socket.io结合express-session使用时中间件不执行next函数

问题根因

  • 你定义的session是无参数工厂函数,调用后才会返回符合(req, res, next)格式的express-session中间件实例。你在io.use中直接给session传入socket.request、空对象和next三个参数,这些参数会被完全忽略,仅返回了新的中间件实例但没有执行,所以next永远不会被调用,握手流程卡住。
  • 手动调用next会跳过session中间件的异步执行流程,session还没挂载到request对象上就进入连接逻辑,自然返回undefined。
  • 额外代码错误:disconnect事件需要在单个socket连接实例上监听,绑定在io实例上不会触发。

修正方案

1. 复用同一个session中间件实例

不要用工厂函数重复创建session实例,直接创建一次全局复用:

const day = 1000 * 60 * 60 * 24; // ms

const sessionStore = MongoStore.create({
    mongoUrl: "mongodb://localhost:27017/zooit",
    collection: "sessions"
});

// 直接创建session中间件实例,不要包一层函数
const sessionMiddleware = expressSession({
    secret: process.env.SECRET_KEY,
    resave: false,
    saveUninitialized: true,
    store: sessionStore,
    cookie: {
        maxAge: day * 30
    }
});

// express中直接使用实例
app.use(sessionMiddleware);

2. 修正socket.io中间件调用

直接用上面创建的中间件实例处理socket握手请求:

io.use((socket, next) => {
    // 调用session中间件,第二个参数为空对象模拟response即可
    sessionMiddleware(socket.request, {}, next);
});

// 仅保留connection事件的全局监听
io.on("connection", require("./socket-controllers/onConnect"));

3. 修正disconnect事件监听位置

disconnect是单连接级别的事件,需要放到onConnect逻辑中绑定到当前socket实例:

// onConnect.js
function onConnect(socket) {
    console.log(`User connected: ${socket.request.session}`);
    // 绑定当前连接的断开事件
    socket.on("disconnect", () => {
        // 你的断开连接处理逻辑
        console.log(`User disconnected: ${socket.request.session}`);
    });
}

额外注意事项

如果前后端部署在不同域名/端口,需要开启跨域凭证配置:

  • 前端socket.io连接时开启withCredentials:
    import { io } from "socket.io-client";
    const socket = io("你的后端服务地址", {
      withCredentials: true
    });
    
  • 后端CORS配置要允许对应前端源,同时开启credentials: true。

内容的提问来源于stack exchange,提问作者Alexander Hunter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 12:12:03