最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - express.session.MemoryStore not returning session? - Stack Overflow

programmeradmin3浏览0评论

It was really easy setting up sessions and using them in PHP. But my website needs to deal with WebSockets. I am facing problem to set up sessions in node.js. I can easily push data without using sessions and it would work fine but when more than one tab is opened the new socket.id is created and previously opened tabs won't function properly. So I have been working on sessions and had problem accessing session store, its logging session not grabbed. I have tried with session.load as well but no luck

How do I get session object and use it in a way that opening other tabs wouldn't affect the functionality and push data from server to client on all tabs?

var express=require('express');
var http = require('http');
var io = require('socket.io');
var cookie = require("cookie");
var connect = require("connect"),
MemoryStore = express.session.MemoryStore,
sessionStore = new MemoryStore();

var app = express();

app.configure(function () {
    app.use(express.cookieParser());
    app.use(express.session({store: sessionStore
        , secret: 'secret'
        , key: 'express.sid'}));
    app.use(function (req, res) {
        res.end('<h2>Hello, your session id is ' + req.sessionID + '</h2>');
    });
});

server = http.createServer(app);
server.listen(3000);

sio = io.listen(server);

var Session = require('connect').middleware.session.Session;

sio.set('authorization', function (data, accept) {
    // check if there's a cookie header
    if (data.headers.cookie) {
        // if there is, parse the cookie
        data.cookie = connect.utils.parseSignedCookies(cookie.parse(data.headers.cookie),'secret');
        // note that you will need to use the same key to grad the
        // session id, as you specified in the Express setup.
        data.sessionID = data.cookie['express.sid'];
        sessionStore.get(data.sessionID, function (err, session) {
            if (err || !session) {
                // if we cannot grab a session, turn down the connection
                console.log("session not grabbed");
                accept('Error', false);
            } else {
                // save the session data and accept the connection
                console.log("session grabbed");
                data.session = session;
                accept(null, true);
            }
        });
    } else {
       // if there isn't, turn down the connection with a message
       // and leave the function.
       return accept('No cookie transmitted.', false);
    }
    // accept the ining connection
    accept(null, true);
});

sio.sockets.on('connection', function (socket) {
    console.log('A socket with sessionID ' + socket.handshake.sessionID 
        + ' connected!');
});

It was really easy setting up sessions and using them in PHP. But my website needs to deal with WebSockets. I am facing problem to set up sessions in node.js. I can easily push data without using sessions and it would work fine but when more than one tab is opened the new socket.id is created and previously opened tabs won't function properly. So I have been working on sessions and had problem accessing session store, its logging session not grabbed. I have tried with session.load as well but no luck

How do I get session object and use it in a way that opening other tabs wouldn't affect the functionality and push data from server to client on all tabs?

var express=require('express');
var http = require('http');
var io = require('socket.io');
var cookie = require("cookie");
var connect = require("connect"),
MemoryStore = express.session.MemoryStore,
sessionStore = new MemoryStore();

var app = express();

app.configure(function () {
    app.use(express.cookieParser());
    app.use(express.session({store: sessionStore
        , secret: 'secret'
        , key: 'express.sid'}));
    app.use(function (req, res) {
        res.end('<h2>Hello, your session id is ' + req.sessionID + '</h2>');
    });
});

server = http.createServer(app);
server.listen(3000);

sio = io.listen(server);

var Session = require('connect').middleware.session.Session;

sio.set('authorization', function (data, accept) {
    // check if there's a cookie header
    if (data.headers.cookie) {
        // if there is, parse the cookie
        data.cookie = connect.utils.parseSignedCookies(cookie.parse(data.headers.cookie),'secret');
        // note that you will need to use the same key to grad the
        // session id, as you specified in the Express setup.
        data.sessionID = data.cookie['express.sid'];
        sessionStore.get(data.sessionID, function (err, session) {
            if (err || !session) {
                // if we cannot grab a session, turn down the connection
                console.log("session not grabbed");
                accept('Error', false);
            } else {
                // save the session data and accept the connection
                console.log("session grabbed");
                data.session = session;
                accept(null, true);
            }
        });
    } else {
       // if there isn't, turn down the connection with a message
       // and leave the function.
       return accept('No cookie transmitted.', false);
    }
    // accept the ining connection
    accept(null, true);
});

sio.sockets.on('connection', function (socket) {
    console.log('A socket with sessionID ' + socket.handshake.sessionID 
        + ' connected!');
});
Share Improve this question edited Feb 20, 2020 at 6:57 mrsrinivas 35.5k13 gold badges133 silver badges130 bronze badges asked Aug 18, 2013 at 18:12 user2626445user2626445 1,0211 gold badge12 silver badges27 bronze badges 5
  • 1 I guess we have to keep track of socket.id but i dont think that is the correct solution – user2626445 Commented Dec 13, 2013 at 15:52
  • Can you say a little more about the behavior you want after new tabs are opened? Do you want them to act like a pletely new client, or do you want them to share the same session? – leorex Commented Dec 15, 2013 at 10:37
  • 3 Does err have anything? Or is it the !session which tells you that there is no session? – hexacyanide Commented Dec 16, 2013 at 3:35
  • session and err are undefined. But sessionStore has all users session data – mrsrinivas Commented Dec 16, 2013 at 12:49
  • I found similar problem [stackoverflow./questions/8863644/… Have you ever try it? [1]: stackoverflow./questions/8863644/… – Moch Lutfi Commented Dec 18, 2013 at 5:12
Add a ment  | 

1 Answer 1

Reset to default 2

Take a look at this article: Session-based Authorization with Socket.IO

Your code works fine, but need 2 improvements to do what you want (send session data to clients from server):

  1. it extracts sessionID during authorization only
  2. it extracts session data from store by this sessionID during connection where you can send data from server to clients in an interval.

Here's the improved code:

var express = require('express');
var connect = require('connect');
var cookie = require('cookie');
var sessionStore = new express.session.MemoryStore();    

var app = express();    

app.use(express.logger('dev'));
app.use(express.cookieParser());
app.use(express.session({store: sessionStore, secret: "secret", key: 'express.sid'}));
// web page
app.use(express.static('public'));    

app.get('/', function(req, res) {
  var body = '';
  if (req.session.views) {
    ++req.session.views;
  } else {
    req.session.views = 1;
    body += '<p>First time visiting? view this page in several browsers :)</p>';
  }
  res.send(body + '<p>viewed <strong>' + req.session.views + '</strong> times.</p>');
});    

var sio = require('socket.io').listen(app.listen(3000));   

sio.set('authorization', function (data, accept) {
    // check if there's a cookie header
    if (data.headers.cookie) {
        // if there is, parse the cookie
        var rawCookies = cookie.parse(data.headers.cookie);
        data.sessionID = connect.utils.parseSignedCookie(rawCookies['express.sid'],'secret');    
        // it checks if the session id is unsigned successfully
        if (data.sessionID == rawCookies['express.sid']) {
            accept('cookie is invalid', false);
        }
    } else {
       // if there isn't, turn down the connection with a message
       // and leave the function.
       return accept('No cookie transmitted.', false);
    }
    // accept the ining connection
    accept(null, true);
});    

sio.sockets.on('connection', function (socket) {
    //console.log(socket);
    console.log('A socket with sessionID ' + socket.handshake.sessionID + ' connected!');
    // it sets data every 5 seconds
    var handle = setInterval(function() {
        sessionStore.get(socket.handshake.sessionID, function (err, data) {
            if (err || !data) {
                console.log('no session data yet');
            } else {
                socket.emit('views', data);
            }
        });
    }, 5000);    

    socket.on('disconnect', function() {
        clearInterval(handle);
    });
});

Then you can have a client page under public/client.html at http://localhost:3000/client.html to see the session data populated from http://localhost:3000:

<html>
<head>
    <script src="/socket.io/socket.io.js" type="text/javascript"></script>
    <script type="text/javascript">
        tick = io.connect('http://localhost:3000/');
        tick.on('data', function (data) {
            console.log(data);
        });

        tick.on('views', function (data) {
            document.getElementById('views').innerText = data.views;
        });

        tick.on('error', function (reason){
          console.error('Unable to connect Socket.IO', reason);
        });

        tick.on('connect', function (){
          console.info('successfully established a working and authorized connection');
        });
    </script>
</head>
<body>
    Open the browser console to see tick-tocks!
    <p>This session is viewed <b><span id="views"></span></b> times.</p>
</body>

发布评论

评论列表(0)

  1. 暂无评论