【问题标题】:Express SessionID differs from SessionID in CookieExpress SessionID 与 Cookie 中的 SessionID 不同
【发布时间】:2012-12-03 22:43:11
【问题描述】:

通过使用给定的示例,我遇到了相应的问题。 在示例中,通过首先重新加载会话在 WebSocket 中使用它:

  socket.on('set value', function (val) {
    sess.reload(function () {
      sess.value = val;
      sess.touch().save();
    });
  });

尝试在我自己的应用程序中使用它,我得到以下异常:

  sess.reload(function () {
       ^
TypeError: Object #<Object> has no method 'reload'

我认为问题在于,没有人将变量 sess 定义为会话:

io.listen(app).set('authorization', function (data, accept) {
  if (!data.headers.cookie) 
    return accept('No cookie transmitted.', false);

  data.cookie = parseCookie(data.headers.cookie);
  data.sessionID = data.cookie['express.sid'];

  store.load(data.sessionID, function (err, session) {
    if (err || !session) return accept('Error', false);

    data.session = session;
    return accept(null, true);
  });
})

也许有些人对此有一个简短的解决方案?

问题已解决:我尝试使用此示例:https://github.com/DanielBaulig/sioe-demo/blob/master/app.js 与 Express 3.0 和 Redis。

因此,我创建了一个 Redis Store (connect-redis) 而不是 MemoryStore:

app.use(express.session({cookie: {expires: new Date(Date.now() + 30*60*60*24*1000)}, secret: SESSION_SECRET, key: SESSION_KEY, store: new RedisStore({host:'localhost', port:'6379', client: dbRedis})}));

由于connect中的parseCookie-Method移动了我使用

parseCookie = require('cookie').parse

而不是

connect.utils.parseCookie

为了访问 cookie 中的会话,我使用以下代码修改了示例:

sio.set('authorization', function (data, accept) {
  if (!data.headers.cookie) 
    return accept('No cookie transmitted.', false);

  data.cookie = parseCookie(data.headers.cookie);
  log.info('Cookie: $s', JSON.stringify(data.cookie));
  data.sessionID = data.cookie['letter.sid'];
  log.info('SessionId: %s', data.sessionID);

  dbRedis.get(data.sessionID, function (err, session) {
    if (err || !session) return accept('Error ' + session, false);

    data.session = session;
    return accept(null, true);
  });
})

现在我的问题是,我无法从 Redis 加载会话,因为会话 ID 不同 在页面上打印会话 ID (req.sessionID) 我得到:n+57bnkLr+iXkMLbStWdFzK5 但在 Redis 中存储了以下 ID:

[2012-12-03T22:14:56.632Z]  INFO: Postbox/78964 on capns-mba.local: Cookie: $s {"SQLiteManager_currentLangue":"4","connect.sid":"s:xvYdDm5C0MEIg53EG8JgqBnM.Tx8+PMKa570zk6qt9vmCjRz2p/LP/COyyqGSm+VKxww","letter.sid":"s:n+57bnkLr+iXkMLbStWdFzK5.XPHh1xXrK9D4cPfJ7HcHO11PKk8FXLg6fIRGaWb/+jI"}
[2012-12-03T22:14:56.632Z]  INFO: Postbox/78964 on capns-mba.local: SessionId: s:n+57bnkLr+iXkMLbStWdFzK5.XPHh1xXrK9D4cPfJ7HcHO11PKk8FXLg6fIRGaWb/+jI

显然 req.sessionID 是保存在 cookie/redis 中的 SessionID 的一部分 - 但为什么呢?哪个是正确的 sessionID?

【问题讨论】:

  • 好的,问题是我没有使用 dbRedis.get() 获得会话。

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


【解决方案1】:

session middleware的这段代码(第267行):

var val = 's:' + signature.sign(req.sessionID, secret);

其中signature.sign 函数是一个串联(伪代码):

req.sessionID + "." + hash(secret)

hash 是一个自定义函数 (see this for more details)。

这意味着它只是 cookie 的签名约定(使其更安全)。您可以通过调用来检索您的 sid:

var signature = require( "cookie-signature" ),
    prefix = "s:";

var real_sid = sid.replace( prefix, "" );
real_sid = signature.unsign( real_sid, SESSION_SECRET );

【讨论】:

  • 在你回答这个问题几年后,今天,你救了一个人的命。谢谢! :)
  • 就我而言,我必须这样做 sid = decodeURIComponent(sid);首先,因为会话 ID 存储在 cookie 中的编码字符串中。
猜你喜欢
  • 1970-01-01
  • 2011-09-21
  • 2019-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-02
  • 1970-01-01
相关资源
最近更新 更多