3

I'm having problems while trying to parse back signed cookies in express/connect application.

io.set('authorization', function (handshakeData, callback) {
    if(handshakeData.headers.cookie) {
        var signedCookies = cookie.parse(decodeURIComponent(handshakeData.headers.cookie));
        handshakeData.cookie = connect.utils.parseSignedCookies(signedCookies, secret);
    } else {
        return accept('No cookie transmitted', false);
    }
    callback(null, true); // error first callback style 
});

What happens is call to connect.utils.parseSignedCookies returns empty object. I looked into source for parse function and found out that it calls unsign method which gets a substring of encoded value and then tries to sign it again with the same secret and compare the results to verify that its the same value encoded and for some reasons it fails and values does not match. I don't know what I'm doing wrong, why those values differs and why I'm unable to get correct session ID.

My app initialization code looks like this:

app.use(express.cookieParser(secret));
app.use(express.session({
    key: 'sessionID',
    secret: secret,
    maxAge: new Date(Date.now() + 3600000),
    store: new RedisStore({
        client: redisClient
    })
}));

Please help and point what I'm doing wrong here. Thank you

4

2 回答 2

2

The cookie parser is a middleware, so we have to use it like one. It will actually populate the object that you pass to it. This is how you would want to be using the parser:

// we need to use the same secret for Socket.IO and Express
var parseCookie = express.cookieParser(secret);

io.set('authorization', function(handshake, callback) {
  if (handshake.headers.cookie) {
    // pass a req, res, and next as if it were middleware
    parseCookie(handshake, null, function(err) {
      // use handshake.signedCookies, since the
      // cookie parser has populated it
    });
  } else {
    return accept('No session.', false);
  }
  callback(null, true);
});

The cookie parser API changed and this is what it looks like now:

module.exports = function cookieParser(secret) {
  return function cookieParser(req, res, next) {
    if (req.cookies) return next();
    var cookies = req.headers.cookie;

    req.secret = secret;
    req.cookies = {};
    req.signedCookies = {};

    if (cookies) {
      try {
        req.cookies = cookie.parse(cookies);
        if (secret) {
          req.signedCookies = utils.parseSignedCookies(req.cookies, secret);
          req.signedCookies = utils.parseJSONCookies(req.signedCookies);
        }
        req.cookies = utils.parseJSONCookies(req.cookies);
      } catch (err) {
        err.status = 400;
        return next(err);
      }
    }
    next();
  };
};

So what we're doing is passing handshake as a request object, and the parser will read the headers.cookie property. Then, the cookies will be parsed, and put into req.signedCookies. Since we passed handshake as req, the cookies are now in handshake.signedCookies. Note that the cookies are only signed because you passed a secret to the parser.

于 2013-09-24T00:51:47.163 回答
0

I was having problems left and right with cookies/sessions/socket.io etc. It was finally @vytautas comment that helped me. In case anyone sees this, please make sure you're connecting to the correct host, whether you have it setup as localhost or an IP address or what have you. Otherwise you won't be able to parse your incoming cookies.

(Seems kind of obvious in hindsight.)

于 2014-01-05T07:48:09.040 回答