【问题标题】:socket.io cookie parse handshake errorsocket.io cookie 解析握手错误
【发布时间】:2012-08-26 09:53:25
【问题描述】:

当 socket.io 查找会话时,我收到握手错误,因为 cookie 的 id 与数据库中的不匹配。我正在使用 Express3、mongodb、connect-mongodb 和 socket.io v0.9.10

例如,console.log(data.sessionID) 的结果,来自包含的 socket.io 代码,将打印出来:

s:eFFkUnQXWdTO7GBRDc11No/a.U6voj5QnxKs1skq766nO7/qJvPEJA73KaQM67qNEs/k

但是当我查看我的数据库上的会话集合时,我得到以下_id:

"_id" : "eFFkUnQXWdTO7GBRDc11No/a",

如您所见,这对应于 s: 之后和句点之前的 data.sessionID。我尝试使用两种不同的 cookie 解析器。下面解析器的代码来自 express 3 中包含的 cookie 模块。我不确定每个 cookie ID 是否都遵循这种模式,所以我不知道我是否应该自己再次解析结果,或者我是否有什么东西做错了。

exports.parseCookie = function(str) {
var obj = {}
var pairs = str.split(/[;,] */);
var encode = encodeURIComponent;
var decode = decodeURIComponent;

pairs.forEach(function(pair) {
    var eq_idx = pair.indexOf('=')
    var key = pair.substr(0, eq_idx).trim()
    var val = pair.substr(++eq_idx, pair.length).trim();

    // quoted values
    if ('"' == val[0]) {
        val = val.slice(1, -1);
    }

    // only assign once
    if (undefined == obj[key]) {
        obj[key] = decode(val);
    }
});

return obj;

};

下面的代码给了我一个握手错误,因为“connect.sid”属性与数据库中的 id 属性不匹配。

io.set('authorization', function (data, accept) {

    if (data.headers.cookie) {
        data.cookie = utils.parseCookie(data.headers.cookie);
        data.sessionID = data.cookie['connect.sid'];
        // **************** //
        console.log(data.sessionID);
        // **************** //
        sessionStore.get(data.sessionID, function (err, session) {
            if (err || ! session) {
                accept('Error', false);
            } else {
                data.session = session;
                data.session.url = data.headers.referer;
                accept(null, true);
            }
        });
    } else {
       return accept('No cookie transmitted.', false);
    }
});

【问题讨论】:

    标签: javascript parsing cookies socket.io


    【解决方案1】:

    我遇到了同样的问题,虽然您的解决方案有效,但您使用的 parseCookie 函数来自旧版本的 connect。 connect 中的新代码现在对 cookie 进行签名,即句点后的额外字符。

    在 express 和 connect 的胆量中搞砸了一些之后,我想出了以下代码。虽然它依赖于一些私有 API 函数 connect (utils.parseSignedCookies),但它至少使用与生成 cookie 相同的代码来解析 cookie,因此对 cookie 的未来变化不那么敏感创建并解析。

    /* cookie: the cookie string from the request headers
     * sid: the session 'key' used with express.session()
     * secret: the session 'secret' used with express.session()
     */
    function parseSessionCookie(cookie, sid, secret) {
      var cookies = require('express/node_modules/cookie').parse(cookie)
        , parsed = require('express/node_modules/connect/lib/utils').parseSignedCookies(cookies, secret)
        ;
      return parsed[sid] || null;
    }
    
    socketIO.set('authorization', function(data, accept) {
      var sid = parseSessionCookie(data.headers.cookie, 'express.sid', 'secret');
      if (sid) {
        sessionStore.get(sid, function(err, session) {
          if (err || !session) {
            accept('Error', false);
          } else {
            data.session = session;
            accept(null, true);
          }
        });
      } else {
        return accept('No cookie transmitted.', false);
      }
    }); 
    

    【讨论】:

      【解决方案2】:

      似乎 sessionStore 键现在是更短的 uid(24)-only 版本,不再是存储在 cookie 中的“长”版本。

      目前我通过执行简单的 split('.')[0] 来检索 uid(24) 部分来修复它: data.sessionID = cookie['express.sid'].split('.')[0];

      【讨论】:

      • 虽然这行得通,但我相信它非常脆弱,如果他们改变 cookie 表示,它会破裂。我在下面发布了一个不那么脆弱的答案(即使它确实使用了私有 API)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-14
      • 2014-07-22
      • 2019-11-17
      • 2017-01-09
      • 2017-06-22
      • 2021-04-10
      相关资源
      最近更新 更多