Как я могу поделиться сеансом с Socket.io 1.0 и Express 4.x? Я использую Redis Store, но считаю, что это не имеет значения. Я знаю, что мне нужно использовать промежуточное ПО для просмотра файлов cookie и получения сеанса, но не знаю, как это сделать. Я искал, но не нашел рабочих
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 } }
Но если я распечатываю сеанс в своих маршрутах, я получаю все переменные сеанса, которые я установил (имя пользователя, идентификатор и т. Д.)Всего полтора месяца назад я столкнулся с той же проблемой, а затем написал обширное сообщение в блоге на эту тему, которое идет вместе с полностью работающим демонстрационным приложением, размещенным на GitHub. Решение полагается на модули узлов express-session , cookie-parser и connect-redis, чтобы связать все. Он позволяет вам получать доступ и изменять сеансы из контекста REST и Sockets, что весьма полезно.
Две важные части - это установка промежуточного программного обеспечения:
app.use(cookieParser(config.sessionSecret)); app.use(session({ store: redisStore, key: config.sessionCookieKey, secret: config.sessionSecret, resave: true, saveUninitialized: true }));
... и настройка сервера 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(); }); }); });
Они идут вместе с простым модулем sessionService, который я сделал, который позволяет вам выполнять некоторые базовые операции с сеансами, и этот код выглядит так:
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); } };
Поскольку для всего этого кода больше, чем это (например, инициализация модулей, работа с сокетами и вызовы REST как на стороне клиента, так и на стороне сервера), я не буду вставлять здесь весь код, вы можете просмотреть его на GitHub и вы можете делать с ним все, что хотите.
источник
экспресс-socket.io-сеанс
готовое решение вашей проблемы. Обычно сеанс, созданный на конце socket.io, имеет другой sid, чем те, которые созданы в express.js
Прежде чем я узнал об этом факте, когда я работал над этим, чтобы найти решение, я обнаружил кое-что немного странное. Сеансы, созданные из экземпляра express.js, были доступны на конце socket.io, но то же самое было невозможно для противоположного. И вскоре я узнал, что мне нужно работать над управлением sid, чтобы решить эту проблему. Но для решения этой проблемы уже был написан пакет. Это хорошо задокументировано и выполняет свою работу. Надеюсь, это поможет
источник
Используя ответ Брэдли Ледерхольца, вот как я заставил его работать на себя. Пожалуйста, обратитесь к ответу Брэдли Ледерхольца для получения дополнительных объяснений.
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);
источник
Я вроде как решил это, но это не идеально. Не поддерживает подписанные файлы cookie и т. Д. Я использовал функцию getcookie в экспресс-сеансе . Измененная функция выглядит следующим образом:
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);
источник
Теперь исходный принятый ответ для меня тоже не работает. Как и @ Rahil051, я использовал модуль express-socket.io-session , и он все еще работает. Этот модуль использует cookie-parser для анализа идентификатора сеанса перед вводом промежуточного программного обеспечения экспресс-сеанса. Я думаю, что это Silmiar в ответ на @pootzko, @Mustafa и @ Kosar.
Я использую эти модули:
"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" }
проверьте данные в 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); }); };
источник