2013-09-23 33 views
3

我在解析express/connect应用程序中的签名cookie时遇到问题。连接签名的cookie解析falsy

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 
}); 

发生什么情况是调用connect.utils.parseSignedCookies返回空对象。我查看了解析函数的源代码,发现它调用了unsign方法,该方法获取编码值的子字符串,然后尝试用相同的秘密再次对其进行签名,并比较结果以验证其编码的值相同,出于某种原因失败并且值不匹配。我不知道我做错了什么,为什么这些值不同,为什么我无法获得正确的会话ID。

我的应用程序初始化代码如下所示:

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

请帮助,并指出我在做什么错在这里。谢谢

回答

2

cookie解析器是一个中间件,所以我们必须像使用它一样。它实际上会填充您传递给它的对象。这是你将要如何使用的解析器:

// 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); 
}); 

该Cookie解析器API改变,这是它看起来像现在:

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(); 
    }; 
}; 

所以我们正在做的是通过handshake作为什么一个请求对象,解析器将读取headers.cookie属性。然后,cookies将被解析,并放入req.signedCookies。由于我们通过handshake作为req,因此Cookie现在位于handshake.signedCookies。请注意,因为您将secret传递给解析器,所以Cookie仅进行了签名。

+0

谢谢您的回答,这种方式更有意义,做到这一点,但遗憾的是它不工作,要么出于某些原因。下面是已签名和重新签名的值的截图 - 它仍然不同:http://grab.by/qyra我真的不知道该怎么办... –

+0

你是如何在你的代码中使用cookie解析器的? – hexacyanide

+0

代码与您的解析部分几乎相同。但我不确定是否将它作为中间件正确添加。它在会话中间件之前和路由器中间件之前。当我回家后,我会尝试发布整个代码,也许会有任何想法.. –

0

我用cookies/sessions/socket.io等左右问题。最终@vytautas评论帮了我。如果有人看到这一点,请确保您连接到正确的主机,无论您是将它设置为本地主机还是IP地址或您有什么。否则,您将无法解析传入的Cookie。

(事后看来似乎有点明显。)