如何在 socket.io 连接中获取持久的快速会话 ID?
How to get persistent express session id in socket.io connection?
我正在构建一个 MEAN 堆栈聊天应用程序。我希望能够在连接处理程序的 socket.io 中获得快速会话 ID。我可以访问 socket.handshake.session.id,但它与 req.session.id 不同。此外 socket.handshake.session.id 在每个套接字上不断变化。
我试图通过查找 connect.sid 密钥从 req.handshake.cookie 获取会话 ID 来解决此问题,但该密钥未在其中定义。
const cors = require('cors'),
express = require('express'),
eSession = require('express-session'),
cookieParser = require('cookie-parser'),
MongoStore = require('connect-mongo')(eSession),
sharedsession = require('express-socket.io-session'),
http = require('http'),
bodyParser = require('body-parser'),
socketio = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = socketio(server);
const port = process.env.PORT || 3000;
//imports
const mongoose = require('./config/dbconnection');
//routes
const user = require('./api/routes/user');
const socketHandle = (io, mStore) => {
io.on('connection', (socket) => {
socket.on('join', (options, callback) => {
console.log(socket.handshake.headers.cookie); //no connect.sid string present
console.log(socket.handshake.session.id) // has value but keeps changing on each io connection and this id is not the same as req.session.id in an api endpoint method
});
});
const corsOptions = {
origin: 'http://localhost:4200',
optionsSuccessStatus: 200
};
const db = mongoose.connection;
const mStore = new MongoStore({ mongooseConnection: db });
const session = eSession({
secret: 'my-secret',
resave: true,
saveUninitialized: true,
store: mStore
});
app.use(cookieParser('my-secret'));
app.use(session);
io.use(sharedsession(session,{autoSave:true}));
socketHandle(io, mStore);
//body-parser
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors(corsOptions));
app.use('/user', user);
server.listen(port, () => console.log(`listening on http://localhost:${port}`));
socket.handshake.session.id 和 socket.handshake.headers.cookie(connect.sid 键)都应该提供与 req.session.id
具有相同值的会话 ID
我试过了,你的代码对我有用,所以我认为你的会话存储有问题。似乎你的 socket.handshake.session 和你的 express-session 之间没有交互,可能是因为你没有把它正确地存储在 mongo 中。试试这个,然后围绕它构建您的应用程序:)
const express = require('express');
const eSession = require('express-session');
const MongoStore = require('connect-mongo')(eSession);
const mongoose = require('mongoose');
const sharedsession = require('express-socket.io-session');
const http = require('http');
const socketio = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = socketio(server);
const port = process.env.PORT || 3000;
const socketHandle = (io) => {
io.on('connection', (socket) => {
console.log(socket.handshake.session.id) // same value on every connection
});
}
// Connect with MongoDB (database called 'test')
mongoose.connect('mongodb://localhost/test', { useNewUrlParser: true, useCreateIndex: true })
.then(() => console.log('Connected with MongoDB!'))
.catch(err => console.log(err));
let db = mongoose.connection;
const mStore = new MongoStore({ mongooseConnection: db });
const session = eSession({
secret: 'my-secret',
resave: true,
saveUninitialized: true,
store: mStore
});
app.use(session);
io.use(sharedsession(session,{autoSave:true}));
socketHandle(io);
// Static folder
app.use(express.static('public')); //Basic html page for socket connection
server.listen(port, () => console.log(`listening on http://localhost:${port}`));
现在,如果您查看会话集合,您会发现它已存储并且 ID 与 handshake.session.id 相同。希望这对你有用:)
我的代码没有任何问题。唯一导致会话 ID 不同的是我 运行 angular 在与节点服务器不同的端口上。我不得不 ng build --watch for angular 并将文件输出到节点服务器的静态文件夹中。通过这样做,我能够在路由和套接字 io 中获得一致的会话 ID。
@Anand Kashyap 是正确的,如果您让快递服务器为您的客户端服务,cookie 将会存在。
然而,当您的客户端在不同的主机上时,您需要将 withCredentials: true 传递给套接字的构造函数。这会将 cookie 附加到请求,会话将正常工作。
const io = require("socket.io-client");
const socket = io("ws://example.com/", {
withCredentials: true,
autoConnect: 10000
});
我正在构建一个 MEAN 堆栈聊天应用程序。我希望能够在连接处理程序的 socket.io 中获得快速会话 ID。我可以访问 socket.handshake.session.id,但它与 req.session.id 不同。此外 socket.handshake.session.id 在每个套接字上不断变化。
我试图通过查找 connect.sid 密钥从 req.handshake.cookie 获取会话 ID 来解决此问题,但该密钥未在其中定义。
const cors = require('cors'),
express = require('express'),
eSession = require('express-session'),
cookieParser = require('cookie-parser'),
MongoStore = require('connect-mongo')(eSession),
sharedsession = require('express-socket.io-session'),
http = require('http'),
bodyParser = require('body-parser'),
socketio = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = socketio(server);
const port = process.env.PORT || 3000;
//imports
const mongoose = require('./config/dbconnection');
//routes
const user = require('./api/routes/user');
const socketHandle = (io, mStore) => {
io.on('connection', (socket) => {
socket.on('join', (options, callback) => {
console.log(socket.handshake.headers.cookie); //no connect.sid string present
console.log(socket.handshake.session.id) // has value but keeps changing on each io connection and this id is not the same as req.session.id in an api endpoint method
});
});
const corsOptions = {
origin: 'http://localhost:4200',
optionsSuccessStatus: 200
};
const db = mongoose.connection;
const mStore = new MongoStore({ mongooseConnection: db });
const session = eSession({
secret: 'my-secret',
resave: true,
saveUninitialized: true,
store: mStore
});
app.use(cookieParser('my-secret'));
app.use(session);
io.use(sharedsession(session,{autoSave:true}));
socketHandle(io, mStore);
//body-parser
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors(corsOptions));
app.use('/user', user);
server.listen(port, () => console.log(`listening on http://localhost:${port}`));
socket.handshake.session.id 和 socket.handshake.headers.cookie(connect.sid 键)都应该提供与 req.session.id
具有相同值的会话 ID我试过了,你的代码对我有用,所以我认为你的会话存储有问题。似乎你的 socket.handshake.session 和你的 express-session 之间没有交互,可能是因为你没有把它正确地存储在 mongo 中。试试这个,然后围绕它构建您的应用程序:)
const express = require('express');
const eSession = require('express-session');
const MongoStore = require('connect-mongo')(eSession);
const mongoose = require('mongoose');
const sharedsession = require('express-socket.io-session');
const http = require('http');
const socketio = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = socketio(server);
const port = process.env.PORT || 3000;
const socketHandle = (io) => {
io.on('connection', (socket) => {
console.log(socket.handshake.session.id) // same value on every connection
});
}
// Connect with MongoDB (database called 'test')
mongoose.connect('mongodb://localhost/test', { useNewUrlParser: true, useCreateIndex: true })
.then(() => console.log('Connected with MongoDB!'))
.catch(err => console.log(err));
let db = mongoose.connection;
const mStore = new MongoStore({ mongooseConnection: db });
const session = eSession({
secret: 'my-secret',
resave: true,
saveUninitialized: true,
store: mStore
});
app.use(session);
io.use(sharedsession(session,{autoSave:true}));
socketHandle(io);
// Static folder
app.use(express.static('public')); //Basic html page for socket connection
server.listen(port, () => console.log(`listening on http://localhost:${port}`));
现在,如果您查看会话集合,您会发现它已存储并且 ID 与 handshake.session.id 相同。希望这对你有用:)
我的代码没有任何问题。唯一导致会话 ID 不同的是我 运行 angular 在与节点服务器不同的端口上。我不得不 ng build --watch for angular 并将文件输出到节点服务器的静态文件夹中。通过这样做,我能够在路由和套接字 io 中获得一致的会话 ID。
@Anand Kashyap 是正确的,如果您让快递服务器为您的客户端服务,cookie 将会存在。
然而,当您的客户端在不同的主机上时,您需要将 withCredentials: true 传递给套接字的构造函数。这会将 cookie 附加到请求,会话将正常工作。
const io = require("socket.io-client");
const socket = io("ws://example.com/", {
withCredentials: true,
autoConnect: 10000
});