2012-12-03 53 views
9

通過使用給出的示例,我有一個相應的問題。 在這個例子中,會話中的WebSocket首先重裝來使用:Express SessionID與Cookie中的SessionID不同

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的存儲(連接-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})})); 

由於parseCookie-法在連接移動我用

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

我現在的問題是,因爲會話ID不同 頁面(req.sessionID)我得到的打印會話ID,我不能加載從Redis的會話: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?

+0

好的問題是,我沒有通過使用dbRedis.get()獲得會話。 – Markus

回答

15

看這一段代碼從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); 
+0

謝謝你解決了我的問題 – Markus

+1

幾年後,你回答了這個問題,今天,你救了一個人的生命。謝謝! :) – geevee

+0

在我的情況下,我不得不做的sid = decodeURIComponent(sid);首先,因爲會話ID存儲在cookie中的編碼字符串中。 –