【已解决】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
根据你提供的信息,问题在于socket.handshake.session
在尝试访问时为undefined
。这通常是因为socket.io
在处理连接授权时没有正确地将会话数据赋值给handshakeData
对象。以下是一些可能的解决方案以及相应的代码示例。
解决方案
首先,确保你已经安装了所需的中间件,例如express-session
和cookie-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-parser
和express-session
在socket.io
的授权之前被应用。 - 会话存储:你需要确保使用的是一个有效的会话存储,例如内存存储或数据库存储。
- 手头数据赋值:在成功获取会话后,将其添加到
handshakeData
对象中,以便后续可以通过socket.handshake.session
访问。
通过这种方式,你可以确保在socket.io
连接过程中正确地传递和访问会话数据。
storeMemory这个方法是怎么写的?
根据你的描述,handshakeData.session
是 undefined
,这表明在 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);
}
});
关键点解释
- 解析 Cookie: 使用
parseCookie
函数将请求头中的cookie
字符串转换成对象。 - 检查 Session ID: 确认
connect.sid
是否存在。 - 获取会话: 在
storeMemory.get
回调中,确保session
存在且不为undefined
或null
。 - 返回结果: 如果会话存在,将其赋值给
handshakeData.session
并调用callback
函数以授权连接。否则,返回错误信息。
调试建议
- 确认
storeMemory.get
方法是否正确实现,并确保它在数据库或内存中正确检索会话数据。 - 使用调试工具或日志记录来确认会话存储库是否按预期工作。
- 检查客户端发送的请求头是否包含正确的
connect.sid
值。
通过这些步骤,你应该能够解决会话认证问题并正确获取到 socket.handshake.session
。