【已解决】Nodejs 关于 socket.io 的(session的认证),获取不到

【已解决】Nodejs 关于 socket.io 的(session的认证),获取不到

 io.set(‘authorization’, function (handshakeData, callback)
{
if (!handshakeData.headers.cookie)
{
return callback(‘no found cookie’, false);
}
handshakeData.cookie =parseCookie(handshakeData.headers.cookie);
console.log(“handshakeData:” + handshakeData.headers.cookie + “&&&&&&&” + handshakeData.cookie);
var connect_sid = handshakeData.cookie[‘connect.sid’];
console.log(“connect_sid:” + connect_sid);
if (connect_sid)
{
storeMemory.get(connect_sid, function (error, session)
{
if (error)
{
callback(error.message, false);
console.log(“session:” + session);
}
else
{
handshakeData.session = session;
!!这里:  console.log(“handshakeData.session:” + handshakeData.session);
callback(null, true);
}
});
}
else
{
callback(‘nosession’);
}
});

日志是这样的 handshakeData:connect.sid=I9L8i7ofxMs%2BzI8%2FBGsSpnpu.zWvUkOt4%2BNlroy0I%2FpLBC3HRbnT6GjzPibo%2FDi%2BPvQk&&&&&&&[object Object]

connect_sid:I9L8i7ofxMs+zI8/BGsSpnpu.zWvUkOt4+Nlroy0I/pLBC3HRbnT6GjzPibo/Di+PvQk

这个就是上面的handshakeData.session:undefined

debug: authorized

info: handshake authorized SWmx1XIsmVBW5_9CnBE_

后面用

var session = socket.handshake.session;
var name = session.user;

错误出现 Cannot read property ‘user’ of undefined


4 回复

根据你提供的信息,问题在于socket.handshake.session在尝试访问时为undefined。这通常是因为socket.io在处理连接授权时没有正确地将会话数据赋值给handshakeData对象。以下是一些可能的解决方案以及相应的代码示例。

解决方案

首先,确保你已经安装了所需的中间件,例如express-sessioncookie-parser

npm install express express-session cookie-parser

然后,你需要确保在设置socket.io的授权之前,这些中间件已经被应用到你的Express应用中。这是非常关键的一步,因为socket.io需要从请求中解析出正确的cookie

示例代码

const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const session = require('express-session');
const cookieParser = require('cookie-parser');

const app = express();
const server = http.createServer(app);
const io = socketIo(server);

// 应用中间件
app.use(cookieParser());
app.use(session({
    secret: 'your_secret_key',
    resave: false,
    saveUninitialized: true
}));

io.set('authorization', function (handshakeData, callback) {
    // 解析cookie
    handshakeData.cookie = parseCookie(handshakeData.headers.cookie);

    // 获取会话ID
    const connect_sid = handshakeData.cookie['connect.sid'];

    if (connect_sid) {
        // 从存储中获取会话数据
        app.get('sessionStore').get(connect_sid, function (error, session) {
            if (error) {
                return callback(error.message, false);
            }

            // 将会话数据添加到handshakeData
            handshakeData.session = session;

            // 继续授权过程
            callback(null, true);
        });
    } else {
        callback('nosession', false);
    }
});

// 监听连接事件
io.on('connection', function (socket) {
    // 现在可以安全地访问session
    const session = socket.handshake.session;
    const name = session.user;
    console.log(name); // 应该输出用户名称
});

server.listen(3000, () => {
    console.log('Server is running on port 3000');
});

解释

  • 中间件顺序:确保cookie-parserexpress-sessionsocket.io的授权之前被应用。
  • 会话存储:你需要确保使用的是一个有效的会话存储,例如内存存储或数据库存储。
  • 手头数据赋值:在成功获取会话后,将其添加到handshakeData对象中,以便后续可以通过socket.handshake.session访问。

通过这种方式,你可以确保在socket.io连接过程中正确地传递和访问会话数据。


storeMemory这个方法是怎么写的?

var storeMemory = new MemoryStore({ reapInterval: 60000 * 10 });

不过最后好了

主要是

,connect = require(‘connect’) ,cookie = require(‘cookie’) ,MemoryStore = connect.middleware.session.MemoryStore

connect的引用我开始是用的express里的,后来单独下载了connect, 然后下面用

handshakeData.cookie = connect.utils.parseSignedCookies(cookie.parse(decodeURIComponent(handshakeData.headers.cookie)),"zcl");

希望有同样错误的同学可以借鉴一下

根据你的描述,handshakeData.sessionundefined,这表明在 storeMemory.get 回调中未能正确设置 handshakeData.session。这可能是因为 storeMemory.get 中的回调函数没有正确处理会话数据。

解决方案

确保会话存储库正确实现了 get 方法,并且在成功获取会话后能够正确地传递给回调函数。以下是改进后的代码示例:

const parseCookie = require('cookie').parse;

io.set('authorization', function (handshakeData, callback) {
    if (!handshakeData.headers.cookie) {
        return callback('no found cookie', false);
    }

    handshakeData.cookie = parseCookie(handshakeData.headers.cookie);
    const connect_sid = handshakeData.cookie['connect.sid'];

    if (connect_sid) {
        storeMemory.get(connect_sid, function (error, session) {
            if (error) {
                return callback(error.message, false);
            }

            // 确保 session 不为 undefined 或 null
            if (session) {
                handshakeData.session = session;
                console.log("handshakeData.session:", handshakeData.session);
                callback(null, true);
            } else {
                callback('no session found', false);
            }
        });
    } else {
        callback('nosession', false);
    }
});

关键点解释

  1. 解析 Cookie: 使用 parseCookie 函数将请求头中的 cookie 字符串转换成对象。
  2. 检查 Session ID: 确认 connect.sid 是否存在。
  3. 获取会话: 在 storeMemory.get 回调中,确保 session 存在且不为 undefinednull
  4. 返回结果: 如果会话存在,将其赋值给 handshakeData.session 并调用 callback 函数以授权连接。否则,返回错误信息。

调试建议

  • 确认 storeMemory.get 方法是否正确实现,并确保它在数据库或内存中正确检索会话数据。
  • 使用调试工具或日志记录来确认会话存储库是否按预期工作。
  • 检查客户端发送的请求头是否包含正确的 connect.sid 值。

通过这些步骤,你应该能够解决会话认证问题并正确获取到 socket.handshake.session

回到顶部