2012-03-12 76 views
4

使用connect,express和socket.io,我嘗試讓我的應用程序在重新連接時獲取會話詳細信息。我的會話顯然可以在客戶端連接的情況下工作,但如果我在瀏覽器上刷新頁面,它會忘記一切。
我的會話cookie絕對是一樣的,所以不是這樣。使用express/connect-redis抓取頁面上的現有會話

我的代碼是我從很多不同來源獲取的片段的大雜燴,因爲似乎並沒有一個完整的示例應用程序。 : -/

我在想什麼?

var qs  = require('querystring'), 
    express = require('express'), 
    app  = express.createServer(), 
    io  = require('socket.io').listen(app.listen(8000)), 
    routes = require('./routes'), 
    pCookie = require('connect').utils.parseCookie, 
    Session = require('connect').middleware.session.Session, 
    RedStore= require('connect-redis')(express), 
    sStore = new RedStore(); 

// Configuration 

app.configure(function(){ 
    app.set('views', __dirname + '/views'); 
    app.set('view engine', 'ejs'); 
    app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(express.cookieParser()); 
    app.use(express.session({ store: sStore, secret: 'tehsecretz' })); 
    app.use(app.router); 
    app.use(express.static(__dirname + '/public')); 
}); 

app.configure('development', function(){ 
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
}); 

app.configure('production', function(){ 
    app.use(express.errorHandler()); 
}); 

// Routes 

app.get('/', routes.index); 

io.sockets.on('connection', function (client) { 
    var hs = client.handshake, 
     session = hs.session; 

    console.log('A socket connected called: ' + hs.sessionId); 

    var intervalId = setInterval(function() { 
     hs.session.reload(function() { 
      hs.session.touch().save(); 
     }); 
    }, 60 * 1000); 

    if (!session.userName) { 
     // Prompts the user for a name on the frontend 
     client.emit('need-to-register'); 
    } 

    client.on('message', function(msg, c) { 
     console.log(session); 
     console.log(msg); 
    }); 

    client.on('register-user', function(data, fn) { 
     // This retrieves the user's name 
     // and - hopefully - saves it to the session. 

     data = qs.parse(data); 
     session.userName = data.username; 

     hs.session.save(); 
     console.log('Saving: ', session); 

     fn('ok'); 
    }); 

    client.on('disconnect', function() { 
     clearInterval(intervalId); 
    }); 
}); 

io.set('authorization', function (data, accept) { 
    if (data.headers.cookie) { 
     data.cookie = pCookie(data.headers.cookie); 
     data.sessionId = data.cookie['connect.sid']; 

     data.sessionStore = sStore; 
     sStore.get(data.sessionId, function (err, session) { 
      if (err || !session) { 
       accept('Error', false); 
      } else { 
       console.log(data.sessionId, session); 
       data.session = new Session(data, session); 
       accept(null, true); 
      } 
     }); 
    } else { 
     return accept('No cookie transmitted', false); 
    } 
}); 

感謝您提供的任何幫助!

+0

簡單的答案是,Socket.IO沒有連接,bodyParser只對連接請求起作用。 Socket.IO具有不同的傳輸方式,並且它們不共享cookie,因此它必須使用HTTP傳輸方式之一,並且您需要Socket.IO的中間件,它可以使用會話cookie進行連接,或者使用連接會話API來檢索會話。 – 2012-03-12 04:14:47

+0

但'sStore'是'connect-redis'的一個實例,所以''authorization'方法中的'sStore.get()'不是處理這個問題的方法嗎?就像我說的那樣,它不像餅乾在變化;在我的腦海中,我會認爲更新會話(從'client.on('register-user'...)')會將其寫入redis,因此在檢索時可供cookie使用。 ....除非我錯過了一些基本的東西,當然。 – Morgon 2012-03-12 04:22:43

回答

3

唉。所以在Daniel Baulig's post的主題上,他引用了標識符sessionID。我認爲這只是一個糟糕的慣例(因爲我習慣了駱駝案件),並立即將其更改爲我的代碼中的sessionId

在我調試時,我打開了MONITOR ing我的redis實例,並注意到會話正在寫入sess:undefined

結果sessionID是特殊的,並在內部引用爲實際標識符。將sessionId的所有實例更改爲sessionID可讓我更好地瞭解誰正在連接!

0

增加 '餅乾' 在 「express.session」

app.use(express.session({ 
    secret: 'exampleSecretKey' 
    ,store: exampleStore 
    ,key: 'example' 
    cookie: { 
     path: '/' 
     ,expires: false // Alive Until Browser Exits 
     ,httpOnly: true 
    // ,domain:'.example.com' 
    } 
}); 
+0

感謝您的迴應,但是這沒有效果。 – Morgon 2012-03-12 05:15:38