Bagaimana saya bisa berbagi sesi dengan Socket.io 1.0 dan Express 4.x? Saya menggunakan Toko Redis, tapi saya yakin itu tidak masalah. Saya tahu saya harus menggunakan middleware untuk melihat cookie dan mengambil sesi, tetapi tidak tahu caranya. Saya mencari tetapi tidak dapat menemukan yang berfungsi
var RedisStore = connectRedis(expressSession);
var session = expressSession({
store: new RedisStore({
client: redisClient
}),
secret: mysecret,
saveUninitialized: true,
resave: true
});
app.use(session);
io.use(function(socket, next) {
var handshake = socket.handshake;
if (handshake.headers.cookie) {
var str = handshake.headers.cookie;
next();
} else {
next(new Error('Missing Cookies'));
}
});
{ path: '/', _expires: null, originalMaxAge: null, httpOnly: true, secure: true } }
Tetapi jika saya mencetak sesi di rute saya, saya mendapatkan semua variabel sesi yang telah saya siapkan (nama pengguna, id, dll ..)Hanya satu setengah bulan yang lalu saya menangani masalah yang sama dan setelah itu menulis posting blog ekstensif tentang topik ini yang sejalan dengan aplikasi demo yang berfungsi penuh yang dihosting di GitHub. Solusinya bergantung pada modul node sesi-ekspres , cookie-parser, dan connect-redis untuk mengikat semuanya. Ini memungkinkan Anda untuk mengakses dan memodifikasi sesi dari konteks REST dan Sockets yang cukup berguna.
Dua bagian penting adalah pengaturan middleware:
app.use(cookieParser(config.sessionSecret)); app.use(session({ store: redisStore, key: config.sessionCookieKey, secret: config.sessionSecret, resave: true, saveUninitialized: true }));
... dan pengaturan server SocketIO:
ioServer.use(function (socket, next) { var parseCookie = cookieParser(config.sessionSecret); var handshake = socket.request; parseCookie(handshake, null, function (err, data) { sessionService.get(handshake, function (err, session) { if (err) next(new Error(err.message)); if (!session) next(new Error("Not authorized")); handshake.session = session; next(); }); }); });
Mereka pergi bersama dengan modul sessionService sederhana yang saya buat yang memungkinkan Anda melakukan beberapa operasi dasar dengan sesi dan kode itu terlihat seperti ini:
var config = require('../config'); var redisClient = null; var redisStore = null; var self = module.exports = { initializeRedis: function (client, store) { redisClient = client; redisStore = store; }, getSessionId: function (handshake) { return handshake.signedCookies[config.sessionCookieKey]; }, get: function (handshake, callback) { var sessionId = self.getSessionId(handshake); self.getSessionBySessionID(sessionId, function (err, session) { if (err) callback(err); if (callback != undefined) callback(null, session); }); }, getSessionBySessionID: function (sessionId, callback) { redisStore.load(sessionId, function (err, session) { if (err) callback(err); if (callback != undefined) callback(null, session); }); }, getUserName: function (handshake, callback) { self.get(handshake, function (err, session) { if (err) callback(err); if (session) callback(null, session.userName); else callback(null); }); }, updateSession: function (session, callback) { try { session.reload(function () { session.touch().save(); callback(null, session); }); } catch (err) { callback(err); } }, setSessionProperty: function (session, propertyName, propertyValue, callback) { session[propertyName] = propertyValue; self.updateSession(session, callback); } };
Karena ada lebih banyak kode untuk semuanya daripada ini (seperti menginisialisasi modul, bekerja dengan soket dan panggilan REST pada klien dan sisi server), saya tidak akan menempelkan semua kode di sini, Anda dapat melihatnya di GitHub dan Anda dapat melakukan apa pun yang Anda inginkan dengannya.
sumber
express-socket.io-session
adalah solusi siap pakai untuk masalah Anda. Biasanya sesi yang dibuat di socket.io end memiliki sid yang berbeda dari yang dibuat di express.js
Sebelum mengetahui fakta itu, ketika saya sedang mengerjakannya untuk menemukan solusinya, saya menemukan sesuatu yang agak aneh. Sesi yang dibuat dari instance express.js dapat diakses di ujung socket.io, tetapi hal yang sama tidak mungkin terjadi sebaliknya. Dan segera saya mengetahui bahwa saya harus bekerja dengan cara saya mengelola sid untuk menyelesaikan masalah itu. Tapi, sudah ada paket yang dibuat untuk mengatasi masalah tersebut. Itu didokumentasikan dengan baik dan menyelesaikan pekerjaan. Semoga membantu
sumber
Menggunakan jawaban Bradley Lederholz, inilah cara saya membuatnya berhasil untuk diri saya sendiri. Silakan merujuk pada jawaban Bradley Lederholz, untuk penjelasan lebih lanjut.
var app = express(); var server = require('http').createServer(app); var io = require('socket.io'); var cookieParse = require('cookie-parser')(); var passport = require('passport'); var passportInit = passport.initialize(); var passportSession = passport.session(); var session = require('express-session'); var mongoStore = require('connect-mongo')(session); var mongoose = require('mongoose'); var sessionMiddleware = session({ secret: 'some secret', key: 'express.sid', resave: true, httpOnly: true, secure: true, ephemeral: true, saveUninitialized: true, cookie: {}, store:new mongoStore({ mongooseConnection: mongoose.connection, db: 'mydb' }); }); app.use(sessionMiddleware); io = io(server); io.use(function(socket, next){ socket.client.request.originalUrl = socket.client.request.url; cookieParse(socket.client.request, socket.client.request.res, next); }); io.use(function(socket, next){ socket.client.request.originalUrl = socket.client.request.url; sessionMiddleware(socket.client.request, socket.client.request.res, next); }); io.use(function(socket, next){ passportInit(socket.client.request, socket.client.request.res, next); }); io.use(function(socket, next){ passportSession(socket.client.request, socket.client.request.res, next); }); io.on('connection', function(socket){ ... }); ... server.listen(8000);
sumber
Saya sudah menyelesaikannya, tapi tidak sempurna. Tidak mendukung cookie yang ditandatangani, dll. Saya menggunakan fungsi getcookie sesi ekspres . Fungsi yang dimodifikasi adalah sebagai berikut:
io.use(function(socket, next) { var cookie = require("cookie"); var signature = require('cookie-signature'); var debug = function() {}; var deprecate = function() {}; function getcookie(req, name, secret) { var header = req.headers.cookie; var raw; var val; // read from cookie header if (header) { var cookies = cookie.parse(header); raw = cookies[name]; if (raw) { if (raw.substr(0, 2) === 's:') { val = signature.unsign(raw.slice(2), secret); if (val === false) { debug('cookie signature invalid'); val = undefined; } } else { debug('cookie unsigned') } } } // back-compat read from cookieParser() signedCookies data if (!val && req.signedCookies) { val = req.signedCookies[name]; if (val) { deprecate('cookie should be available in req.headers.cookie'); } } // back-compat read from cookieParser() cookies data if (!val && req.cookies) { raw = req.cookies[name]; if (raw) { if (raw.substr(0, 2) === 's:') { val = signature.unsign(raw.slice(2), secret); if (val) { deprecate('cookie should be available in req.headers.cookie'); } if (val === false) { debug('cookie signature invalid'); val = undefined; } } else { debug('cookie unsigned') } } } return val; } var handshake = socket.handshake; if (handshake.headers.cookie) { var req = {}; req.headers = {}; req.headers.cookie = handshake.headers.cookie; var sessionId = getcookie(req, "connect.sid", mysecret); console.log(sessionId); myStore.get(sessionId, function(err, sess) { console.log(err); console.log(sess); if (!sess) { next(new Error("No session")); } else { console.log(sess); socket.session = sess; next(); } }); } else { next(new Error("Not even a cookie found")); } }); // Session backend config var RedisStore = connectRedis(expressSession); var myStore = new RedisStore({ client: redisClient }); var session = expressSession({ store: myStore, secret: mysecret, saveUninitialized: true, resave: true }); app.use(session);
sumber
Sekarang, jawaban asli yang diterima juga tidak berhasil untuk saya. Sama seperti @ Rahil051, saya menggunakan modul express-socket.io-session , dan masih berfungsi. Modul ini menggunakan cookie-parser, untuk mengurai id sesi sebelum memasuki middleware sesi ekspres. Saya pikir itu konyol untuk jawaban @pootzko, @Mustafa dan @ Kosar.
Saya menggunakan modul ini:
"dependencies": { "debug": "^2.6.1", "express": "^4.14.1", "express-session": "^1.15.1", "express-socket.io-session": "^1.3.2 "socket.io": "^1.7.3" }
lihat data di socket.handshake:
const debug = require('debug')('ws'); const sharedsession = require('express-socket.io-session'); module.exports = (server, session) => { const io = require('socket.io').listen(server); let connections = []; io.use(sharedsession(session, { autoSave: true, })); io.use(function (socket, next) { debug('check handshake %s', JSON.stringify(socket.handshake, null, 2)); debug('check headers %s', JSON.stringify(socket.request.headers)); debug('check socket.id %s', JSON.stringify(socket.id)); next(); }); io.sockets.on('connection', (socket) => { connections.push(socket); }); };
sumber