সকেট.আইও 1.x এবং এক্সপ্রেস 4.x এর সাথে সেশনগুলি কীভাবে ভাগ করবেন?


91

আমি কীভাবে সকেট.আই.ओ. 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'));
        }
    });

উত্তর:


219

সমাধান আশ্চর্যজনকভাবে সহজ। এটি খুব ভাল নথিভুক্ত নয়। এক্সপ্রেস সেশন মিডলওয়্যারটি সকেট হিসাবে ব্যবহার করা সম্ভব। আইও মিডলওয়্যারটিও এর মতো ছোট অ্যাডাপ্টারের সাথে:

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

18
আপনি কি আমাকে সমাধান করতে সাহায্য করতে পারেন? আমি কেবল এই ডেটাটিই পাই get কুকি: { path: '/', _expires: null, originalMaxAge: null, httpOnly: true, secure: true } }তবে আমি যদি আমার রুটে সেশনটি প্রিন্ট করি তবে আমি সেট করে রেখেছি সমস্ত সেশন ভেরিয়েবলগুলি (ব্যবহারকারীর নাম, আইডি, ইত্যাদি) পেয়েছি
ববি শার্ক

7
এটি তাদের ডক্সে পুরোপুরি যুক্ত হওয়া উচিত। প্রমাণীকরণের ডকুমেন্টেশনগুলি বর্তমানে যেমন রয়েছে তেমন হালকা।
ব্রেট

4
এটি আমার জন্য "কাজ করে" তবে আমার এক্সপ্রেস সেশন আইডিটি আমার সকেট.ইও সেশন আইডির মতো নয় ... সম্ভবত আমি কি চাই না যে তারা যাইহোক একইভাবে হয়?
আলেকজান্ডার মিলস

4
এই সমাধান মহান কাজ! ... যতক্ষণ না আমার সকেটের মধ্যে সেশনে ডেটা সংরক্ষণ করার দরকার ছিল। এমন সময়ে (আমি) এটি দেখতে পাচ্ছি যে এটির একমাত্র উপায়। এটি উভয় উপায়ে কাজ করার কোনও উপায় আছে?
আইডিভিবি

4
এটি বেশ কয়েকটি সংশোধন করে দুর্দান্ত কাজ করেছে। কিন্তু আমি সকেট.ইও থেকে অধিবেশনটিতে লিখতে পারি নি। আমি একটি এনপিএম প্যাকেজ পেয়েছি যা আমার সমস্ত চাহিদা পূরণ করেছে এবং বাস্তবায়নের উত্তর হিসাবে একই প্রচেষ্টা নিয়েছে। npmjs.com/package/express-sket.io-session
বেকন ব্র্যাড

6

দেড় মাস আগে আমি একই সমস্যাটি মোকাবিলা করেছি এবং এরপরে এই বিষয়টিতে একটি বিস্তৃত ব্লগ পোস্ট লিখেছিলাম যা গিটহাবের উপর হোস্ট করা সম্পূর্ণরূপে কাজ করা ডেমো অ্যাপ্লিকেশনটির সাথে একসাথে চলেছে। সমাধান এক্সপ্রেস-সেশন , কুকি-পার্সার এবং কানেক্ট-রেডিস নোড মডিউলগুলিকে সবকিছু বেঁধে রাখার উপর নির্ভর করে । এটি আপনাকে আরইএসটি এবং সকেট উভয় প্রসঙ্গ থেকে সেশন অ্যাক্সেস এবং সংশোধন করতে দেয় যা বেশ কার্যকর।

দুটি গুরুত্বপূর্ণ অংশ হ'ল মিডলওয়্যার সেটআপ:

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

যেহেতু এর চেয়ে পুরো বিষয়টিতে আরও কোড রয়েছে (যেমন মডিউলগুলি আরম্ভ করা, ক্লায়েন্ট এবং সার্ভার উভয় পক্ষেই সকেট এবং আরএসটি কলগুলির সাথে কাজ করা), আমি এখানে সমস্ত কোড পেষ্ট করব না, আপনি এটি গিটহাবে দেখতে পারেন এবং আপনি এটি দিয়ে যা করতে পারেন তা করতে পারেন।


4

এক্সপ্রেস-সকেট.ইও-সেশন

আপনার সমস্যার জন্য প্রস্তুত সমাধান। সাধারণত সকেট.ইও প্রান্তে তৈরি অধিবেশন এক্সপ্রেস.জেএস-তে তৈরি হওয়া পদের চেয়ে আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা আলাদা টিউস এর এক্সচেঞ্জের তৈরি করা হয়েছে

এই সত্যটি জানার আগে, যখন আমি সমাধানটি অনুসন্ধানের জন্য এটির মাধ্যমে কাজ করছি, তখন আমি কিছুটা অদ্ভুত কিছু পেয়েছি। এক্সপ্রেস.জেস উদাহরণ থেকে তৈরি সেশনগুলি সকেট.ইও প্রান্তে অ্যাক্সেসযোগ্য ছিল, তবে বিপরীতে এটি একইভাবে সম্ভব ছিল না। এবং শীঘ্রই আমি জানতে পারি যে সমস্যাটি সমাধান করার জন্য আমাকে সিড পরিচালনার মাধ্যমে আমার কাজ করতে হবে। তবে, ইতিমধ্যে এই জাতীয় সমস্যা মোকাবেলায় একটি প্যাকেজ লেখা হয়েছিল। এটি ভাল নথিভুক্ত এবং কাজ সম্পন্ন হয়। আশা করি এটা সাহায্য করবে


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

আমার জন্য কাজ করেছেন। Socket.request.user আমার ব্যবহারকারীকে খুঁজে পেয়েছি
Milazi

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 হিসাবে একই, আমি এক্সপ্রেস-সকেট.আইও-সেশন মডিউল ব্যবহার করেছি এবং এটি এখনও কার্যকর। এক্সপ্রেস-সেশন মিডলওয়্যার প্রবেশের আগে সেশন আইডি পার্স করতে এই মডিউলটি কুকি-পার্সার ব্যবহার করে। আমি মনে করি এটি @ পুটজকো, @ মুস্তফা এবং @ কোসার এর উত্তরের সিলিমিয়ার।

আমি এই মডিউলগুলি ব্যবহার করছি:

"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);
    });
};
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.