2013-08-18 34 views
16

这是很容易建立会话和在PHP中使用它们。但我的网站需要处理websockets。我面临着在node.js中设置会话的问题。我可以在不使用会话的情况下轻松推送数据,但它可以正常工作,但是当打开多个选项卡时,会创建新的socket.id,并且之前打开的选项卡将无法正常工作。所以我一直在研究会话,并且访问sessionstore时遇到了问题,它的日志记录会话没有被抓住。我曾尝试与session.load很好,但没有运气express.session.MemoryStore不返回会话?

如何获取会话对象和的方式,打开其他选项卡难道不影响功能和服务器数据推送到客户端上的所有选项卡使用它呢?

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

我猜我们必须跟踪socket.id,但我不认为这是正确的解决方案 – user2626445

+0

你可以在新标签打开后多说一点你想要的行为吗?你想让他们像一个全新的客户端,还是希望他们分享同一个会话? – leorex

+3

'err'有什么?或者是'!session'告诉你没有会话? – hexacyanide

回答

1

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

你的代码工作正常,但需要2个改进做你想要的(从服务器发送会话数据,客户端):

  1. 它摘录sessionID期间授权只有
  2. 它提取会议数据从此存储此sessionID连接ection您可以在此间隔内从服务器向客户端发送数据。

这里的改进代码:

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

然后你就可以在http://localhost:3000/client.htmlpublic/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>