Node.js session 用mongodb存储之 socket.io访问session的值

天做到聊天室问题的时候,登录成功保存或更新mongodbsession信息,想要在socket对话的时候验证和获得session的信息,如果存在session,转发信息,否则返回一个提示并关闭socket连接。

    关于mongodb存储session在之前已经讲述使用connect-mongo来管理session的信息,但是socket如何获得session的信息并且和前端的连接的socket handshake的cookie ID 一致。在网上找到了解决方案,不过只适合在connect-redis使用可以下载代码npm install session.socket.io预读代码,代码很少,我只修改了部分代码完成了想要的功能。代码如下:

01 module.exports = function(io, sessionStore, cookieParser, key) {
02   key = key || 'connect.sid';
03  
04   this.of = function(namespace) {
05     return {
06       on: function(event, callback) {
07         return bind.call(this, event, callback, io.of(namespace));
08       }.bind(this)
09     };
10   };
11  
12   this.on = function(event, callback) {
13     return bind.call(this, event, callback, io.sockets);
14   };
15  
16   this.getSession = function(socket, callback) {
17     cookieParser(socket.handshake, {}, function (parseErr) {
18         var sessionid = socket.handshake.cookies[key];
19         //由于cookie保存如下,mongodb保存的_id为sessionID的加密格式,为ypbxGhOzzAQDlsn3mmVGrO6A,获取想要的串就ok
20         //s:ypbxGhOzzAQDlsn3mmVGrO6A.9rtRxhQu3r8ymOZ1s%2FzlfEWaZ9MSorSBobzy8CNhjh0
21         var sid = '';
22         if(sessionid)
23         {
24            sid =  sessionid.split(':')[1].split('.')[0];
25         }
26       sessionStore.get(sid, function (storeErr, session) {
27         var err = resolve(parseErr, storeErr, session);
28         callback(err, session);
29       });
30     });
31   };
32  
33   function bind(event, callback, namespace) {
34     namespace.on(event, function (socket) {
35       this.getSession(socket, function (err, session) {
36         callback(err, socket, session);
37       });
38     }.bind(this));
39   }
40  
41   function findCookie(handshake) {
42     return (handshake.secureCookies && handshake.secureCookies[key])
43         || (handshake.signedCookies && handshake.signedCookies[key])
44         || (handshake.cookies && handshake.cookies[key]);
45   }
46  
47   function resolve(parseErr, storeErr, session) {
48     if (parseErr) return parseErr;
49     if (!storeErr && !session) return new Error ('could not look up session by key: ' + key);
50     return storeErr;
51   }
52 };

现在socket链接的时候使用如下代码

01 var SessionSockets  = require('./session.socket.io');//也就是以上的代码片段
02 var sessionStore = new MongoStore({
03         url:settings.mongodb.host
04     });
05 var cookieParser =express.cookieParser('world');
06 //当然这里还有很多配置
07 //jsessionid为云存储统一制定id,单机可要可不要参见http://blog.cloudfoundry.com/2013/01/24/scaling-real-time-apps-on-cloud-foundry-using-node-js-and-redis/
08 var sessionSockets = new SessionSockets(io,sessionStore,cookieParser,'jsessionid');
09 sessionSockets.on('connection'function (err,socket,session) {
10         console.log('-session',session.jsessionid);//在登录的时候只要设置req.session.jsessionid就可以得到此ID
11 })

    于,感觉上面的方法有些繁琐,于是另辟蹊径,果然找到了更加简易的方法,socket.io自带有一个握手验证方法authorization,这个方法在链接的时候验证是否登录成功,那我们可以根据会话成功修改成我们设定的sessionID,以便于我们在socket可以访问到。上代码:

01  //第二个参数和第三个参数和以上一样
02  module.exports = function (io,sessionStore,cookieParser) {
03     //验证并设置session
04     io.set('authorization'function(handshakeData, callback){
05         // 通过客户端的cookie字符串来获取其session数据
06         handshakeData.cookie = cookie.parseCookie(handshakeData.headers.cookie)
07         var sessionid = handshakeData.cookie['connect.sid'];//这是默认的,可以在app.use(express.session({key:'userid'})的这个key来修改默认
08         if (sessionid) {
09             //由于cookie保存如下,mongodb保存的_id为sessionID的加密格式,为ypbxGhOzzAQDlsn3mmVGrO6A,获取想要的串就ok
10             //s:ypbxGhOzzAQDlsn3mmVGrO6A.9rtRxhQu3r8ymOZ1s%2FzlfEWaZ9MSorSBobzy8CNhjh0
11             var sid = '';
12             if(sessionid)
13             {
14                 sid =  sessionid.split(':')[1].split('.')[0];
15             }
16             sessionStore.get(sid, function(error, session){
17                 if (error) {
18                     // if we cannot grab a session, turn down the connection
19                     callback(error.message, false);
20                 }
21                 else {
22                     //console.log('session,',session)
23                     // save the session data and accept the connection
24                     handshakeData.session = session;
25                     callback(nulltrue);
26                 }
27             });
28         }
29         else {
30             callback('nosession');
31         }
32     });
33     //开始监听客户端连接
34     io.on('connection'function (socket) {
35         console.log("Connection " + socket.id + " accepted.");
36         //如下使用可以拿到session里的userid
37         console.log('-session',socket.handshake.session.userid);
38  
39         //从客户端接受消息
40         socket.on('message',function(msg){
41  
42         })
43     })
44 }

不过感觉最开始那种更全面点哈。特别是对cookie的类型获取验证


转自:http://my.oschina.net/antianlu/blog/187254

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值