express.session.MemoryStore没有返回会话?

时间:2013-08-18 18:12:09

标签: javascript node.js session express socket.io

设置会话并在php中使用它们非常简单。但我的网站需要处理websockets。我在node.js中设置会话时遇到问题。我可以轻松地推送数据而不使用会话,它可以正常工作但是当打开多个选项卡时,会创建新的socket.id并且之前打开的选项卡将无法正常运行。所以我一直在处理会话,并且在访问会话库时遇到问题,没有抓取其日志记录会话。我也尝试过session.load,但没有运气

如何获取会话对象并以打开其他选项卡不会影响功能并在所有选项卡上将数​​据从服务器推送到客户端的方式使用它?

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 incoming connection
    accept(null, true);
});

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

1 个答案:

答案 0 :(得分:1)

看一下这篇文章:Session-based Authorization with Socket.IO

您的代码运行正常,但需要进行2项改进才能完成所需(从服务器向客户端发送会话数据):

  1. 仅在授权
  2. 期间提取sessionID
  3. 它会在连接期间通过此sessionID从商店中提取会话数据,您可以在此时间间隔内将数据从服务器发送到客户端。
  4. 以下是改进的代码:

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

    然后,您可以在public/client.html http://localhost:3000/client.html下方设置一个客户页面,以查看从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>