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预读代码,代码很少,我只修改了部分代码完成了想要的功能。代码如下:

module.exports = function(io, sessionStore, cookieParser, key) {
  key = key || 'connect.sid';

  this.of = function(namespace) {
    return {
      on: function(event, callback) {
        return bind.call(this, event, callback, io.of(namespace));
      }.bind(this)
    };
  };

  this.on = function(event, callback) {
    return bind.call(this, event, callback, io.sockets);
  };

  this.getSession = function(socket, callback) {
    cookieParser(socket.handshake, {}, function (parseErr) {
        var sessionid = socket.handshake.cookies[key];
        //由于cookie保存如下,mongodb保存的_id为sessionID的加密格式,为ypbxGhOzzAQDlsn3mmVGrO6A,获取想要的串就ok
        //s:ypbxGhOzzAQDlsn3mmVGrO6A.9rtRxhQu3r8ymOZ1s%2FzlfEWaZ9MSorSBobzy8CNhjh0
        var sid = '';
        if(sessionid)
        {
           sid =  sessionid.split(':')[1].split('.')[0];
        }
      sessionStore.get(sid, function (storeErr, session) {
        var err = resolve(parseErr, storeErr, session);
        callback(err, session);
      });
    });
  };

  function bind(event, callback, namespace) {
    namespace.on(event, function (socket) {
      this.getSession(socket, function (err, session) {
        callback(err, socket, session);
      });
    }.bind(this));
  }

  function findCookie(handshake) {
    return (handshake.secureCookies && handshake.secureCookies[key])
        || (handshake.signedCookies && handshake.signedCookies[key])
        || (handshake.cookies && handshake.cookies[key]);
  }

  function resolve(parseErr, storeErr, session) {
    if (parseErr) return parseErr;
    if (!storeErr && !session) return new Error ('could not look up session by key: ' + key);
    return storeErr;
  }
};

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

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

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

 //第二个参数和第三个参数和以上一样
 module.exports = function (io,sessionStore,cookieParser) {
    //验证并设置session
    io.set('authorization', function(handshakeData, callback){
        // 通过客户端的cookie字符串来获取其session数据
        handshakeData.cookie = cookie.parseCookie(handshakeData.headers.cookie)
        var sessionid = handshakeData.cookie['connect.sid'];//这是默认的,可以在app.use(express.session({key:'userid'})的这个key来修改默认
        if (sessionid) {
            //由于cookie保存如下,mongodb保存的_id为sessionID的加密格式,为ypbxGhOzzAQDlsn3mmVGrO6A,获取想要的串就ok
            //s:ypbxGhOzzAQDlsn3mmVGrO6A.9rtRxhQu3r8ymOZ1s%2FzlfEWaZ9MSorSBobzy8CNhjh0
            var sid = '';
            if(sessionid)
            {
                sid =  sessionid.split(':')[1].split('.')[0];
            }
            sessionStore.get(sid, function(error, session){
                if (error) {
                    // if we cannot grab a session, turn down the connection
                    callback(error.message, false);
                }
                else {
                    //console.log('session,',session)
                    // save the session data and accept the connection
                    handshakeData.session = session;
                    callback(null, true);
                }
            });
        }
        else {
            callback('nosession');
        }
    });
    //开始监听客户端连接
    io.on('connection', function (socket) {
        console.log("Connection " + socket.id + " accepted.");
        //如下使用可以拿到session里的userid
        console.log('-session',socket.handshake.session.userid);

        //从客户端接受消息
        socket.on('message',function(msg){

        })
    })
}

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


你可能感兴趣的:(session,Socket.IO,解决方案)