सॉकेट.आईओ 1.x और एक्सप्रेस 4.x के साथ सत्र कैसे साझा करें?


89

मैं सॉकेट.आईओ 1.0 और एक्सप्रेस 4.x के साथ एक सत्र कैसे साझा कर सकता हूं? मैं एक रेडिस स्टोर का उपयोग करता हूं, लेकिन मेरा मानना ​​है कि इससे कोई फर्क नहीं पड़ना चाहिए। मुझे पता है कि मुझे कुकीज़ और लाने के सत्र को देखने के लिए एक मिडलवेयर का उपयोग करना होगा, लेकिन पता नहीं कैसे। मैंने खोजा लेकिन कोई काम नहीं मिला

    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'));
        }
    });

जवाबों:


215

समाधान आश्चर्यजनक रूप से सरल है। यह अभी बहुत अच्छी तरह से प्रलेखित नहीं है। एक्सप्रेस सत्र मिडलवेयर को सॉकेट के रूप में उपयोग करना संभव है। इस तरह के एक छोटे एडेप्टर के साथ भी मिडलवेयर:

sio.use(function(socket, next) {
    sessionMiddleware(socket.request, socket.request.res, next);
});

यहाँ एक्सप्रेस 4.x, सॉकेट.आईओ 1.x और रेडिस के साथ एक पूर्ण उदाहरण है:

var express = require("express");
var Server = require("http").Server;
var session = require("express-session");
var RedisStore = require("connect-redis")(session);

var app = express();
var server = Server(app);
var sio = require("socket.io")(server);

var sessionMiddleware = session({
    store: new RedisStore({}), // XXX redis server config
    secret: "keyboard cat",
});

sio.use(function(socket, next) {
    sessionMiddleware(socket.request, socket.request.res || {}, next);
});

app.use(sessionMiddleware);

app.get("/", function(req, res){
    req.session // Session object in a normal request
});

sio.sockets.on("connection", function(socket) {
  socket.request.session // Now it's available from Socket.IO sockets too! Win!
});


server.listen(8080);

17
क्या आप अपने समाधान में मेरी मदद कर सकते हैं? मुझे केवल यह डेटा {कुकी: मिलता है, { path: '/', _expires: null, originalMaxAge: null, httpOnly: true, secure: true } }लेकिन अगर मैं अपने मार्गों में सत्र को प्रिंट करता हूं तो मुझे मेरे द्वारा सेट किए गए सभी सत्र चर मिलते हैं (उपयोगकर्ता नाम, आईडी, आदि)
बॉबी शार्क

7
यह पूरी तरह से उनके डॉक्स में जुड़ जाना चाहिए। प्रमाणीकरण प्रलेखन सुपर प्रकाश है क्योंकि वे वर्तमान में हैं।
ब्रेट

4
यह मेरे लिए "काम करता है", लेकिन मेरी एक्सप्रेस सेशन आईडी मेरी सॉकेट.आईओ सत्र आईडी के समान नहीं है ... शायद मैं वास्तव में उन्हें वैसे ही नहीं चाहता हूं?
अलेक्जेंडर मिल्स

4
यह समाधान महान काम किया! ... जब तक मुझे उस सॉकेट के भीतर से सत्र को डेटा को बचाने की आवश्यकता होती है, तब () उस बिंदु पर मैं यह पा रहा हूं कि इसका एकमात्र तरीका है। क्या यह दोनों तरीकों से काम करने का एक तरीका है?
०१:११ पर ११'१५

4
इसने कुछ संशोधनों के साथ काम किया। लेकिन मैं socket.io से सत्र को नहीं लिख सका। मुझे एक एनपीएम पैकेज मिला जो मेरी सभी जरूरतों को पूरा करता है और इसे लागू करने के लिए उत्तर के रूप में उसी प्रयास के बारे में लेता है। npmjs.com/package/express-socket.io-session
बेकन ब्रैड

6

डेढ़ महीने पहले मैंने उसी समस्या से निपटा और बाद में इस विषय पर एक व्यापक ब्लॉग पोस्ट लिखी, जो गीथहब पर होस्ट किए गए पूरी तरह से काम कर रहे डेमो ऐप के साथ जाती है। समाधान एक्सप्रेस-सत्र , कुकी-पार्सर और कनेक्ट-रेडिस नोड मॉड्यूल पर निर्भर करता है ताकि सब कुछ टाई हो सके। यह आपको REST और सॉकेट्स संदर्भ से सत्रों को एक्सेस और संशोधित करने की अनुमति देता है जो काफी उपयोगी है।

दो महत्वपूर्ण भाग मिडलवेयर सेटअप हैं:

app.use(cookieParser(config.sessionSecret));
app.use(session({
    store: redisStore,
    key: config.sessionCookieKey,
    secret: config.sessionSecret,
    resave: true,
    saveUninitialized: true
}));

... और सॉकेटियो सर्वर सेटअप:

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();
        });
    });
});

वे एक साधारण सेशन सर्विस मॉड्यूल के साथ जाते हैं, जो मैंने बनाया है जो आपको सत्रों के साथ कुछ बुनियादी संचालन करने की अनुमति देता है और यह कोड इस तरह दिखता है:

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 पर देख सकते हैं और आप इसके साथ जो चाहें कर सकते हैं।


4

व्यक्त-socket.io सत्र

आपकी समस्या के लिए एक तैयार समाधान है। आम तौर पर सॉकेट.आईओ अंत में बनाए गए सत्र में व्यक्त में बनाए गए की तुलना में अलग-अलग साइड होते हैं

उस तथ्य को जानने से पहले, जब मैं समाधान खोजने के लिए इसके माध्यम से काम कर रहा था, तो मुझे कुछ अजीब सा लगा। एक्सप्रेस.जेएस उदाहरण से बनाए गए सत्र सॉकेट.आईओ अंत में सुलभ थे, लेकिन विपरीत के लिए यह संभव नहीं था। और जल्द ही मुझे पता चला कि मुझे उस समस्या को हल करने के लिए प्रबंधन के माध्यम से अपना काम करना है। लेकिन, इस तरह के मुद्दे से निपटने के लिए पहले से ही एक पैकेज लिखा हुआ था। यह अच्छी तरह से प्रलेखित है और काम हो जाता है। आशा करता हूँ की ये काम करेगा


2

ब्रैडली लेदरहोलज़ के उत्तर का उपयोग करते हुए, यह है कि मैंने इसे अपने लिए कैसे काम किया। अधिक स्पष्टीकरण के लिए कृपया ब्रैडली लेदरहोलज़ के उत्तर को देखें।

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);

मेरे लिए काम किया। मेरे उपयोगकर्ता को सॉकेट.request.user
मिलाज़ी

0

मैंने इसे हल किया है, लेकिन यह सही नहीं है। हस्ताक्षरित कुकीज़ आदि का समर्थन नहीं करता है, मैंने एक्सप्रेस-सत्र के गेटकॉकी फ़ंक्शन का उपयोग किया है। संशोधित कार्य निम्नानुसार है:

    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);

0

अब, मूल स्वीकृत उत्तर मेरे लिए भी काम नहीं करता है। @ राहिल 051 के रूप में, मैंने एक्सप्रेस-सॉकेट.आईओ-सत्र का उपयोग किया मॉड्यूल का उपयोग किया, और यह अभी भी काम करता है। यह मॉड्यूल एक्सप्रेस-सत्र मिडलवेयर में प्रवेश करने से पहले सत्र आईडी को पार्स करने के लिए कुकी-पार्सर का उपयोग करता है। मुझे लगता है कि यह @pootzko, @Mustafa और @ कोसर के जवाब के लिए silmiar है।

मैं इन मॉड्यूल का उपयोग कर रहा हूं:

"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"
}

सॉकेट में डेटा देखें।

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);
    });
};
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.