2013-03-02 36 views
2

我有一個簡單的node.js服務器測試connect-redis模塊作爲會話存儲。這一切都有效,但我注意到,在每次請求中,我都會在redis中獲得一個新的sess:密鑰。由於只有一個會話,因此我只希望只有一個密鑰。爲什麼我在每次請求時在redis中看到一個新的sess:key?

redis-cli showing multiple sess: keys

這裏是我的代碼:

var connect = require('connect'); 
var util = require("util"); 
var RedisStore = require("connect-redis")(connect); 
var http = require('http'); 

var app = connect() 
    .use(connect.cookieParser('keyboard cat')) 
    .use(connect.query()) 
    .use(connect.session({ 
     secret:"elms", 
     store:new RedisStore({prefix:'sid_'}), 
     cookie:{maxAge:60000, secure:false} 
    })) 
    .use(function(req, res, next) { 
    var sess = req.session; 
    if (sess.views) { 
     res.setHeader('Content-Type', 'text/html'); 
     res.write("<p>" + util.inspect(req.cookies) + "</p>"); 
     sess.basket = sess.basket || {book1:0, book2:0, book3:0}; 
     if(req.query.buyBook1) {sess.basket.book1 ++;} 
     if(req.query.buyBook2) {sess.basket.book2 ++;} 
     if(req.query.buyBook3) {sess.basket.book3 ++;} 
     if(req.query.expiresession) { 
     sess.cookie.maxAge = 0; 
     } 
     res.write('<p>views: ' + sess.views + '</p>'); 
     res.write('<ul>\ 
        <li>book1 ' + sess.basket.book1 + ' - <a href="/?buyBook1=true">Add</a></li>\ 
        <li>book2 ' + sess.basket.book2 + ' - <a href="/?buyBook2=true">Add</a></li>\ 
        <li>book3 ' + sess.basket.book3 + ' - <a href="/?buyBook3=true">Add</a></li>\ 
       </ul>\ 
       <a href="/?expiresession=true">Expire session</a>'); 
     res.write('<p>expires in: ' + (sess.cookie.maxAge/1000) + 's</p>'); 
     res.write('<p>httpOnly: ' + sess.cookie.httpOnly + '</p>'); 
     res.write('<p>path: ' + sess.cookie.path + '</p>'); 
     res.write('<p>domain: ' + sess.cookie.domain + '</p>'); 
     res.write('<p>secure: ' + sess.cookie.secure + '</p>'); 
     sess.views ++; 
    } else { 
     sess.views = 1; 
    } 

    res.write("<p>" + util.inspect(req.cookies) + "</p>"); 
    res.end('welcome to the session demo. refresh!'); 
    }); 
http.createServer(app).listen(3000); 

我已經注意到,req.session.cookie.domain總是空。我在Windows 8上,使用hosts文件將127.0.0.1映射到www.gaz-node.com,這是我將cookie域放在服務器上。可能有關係。

任何想法? 謝謝

+0

您可以輕鬆地檢查會話是否在客戶端創建。應該設置一個名爲connect.sid的僅有http的cookie,如果不是的話,那麼您的cookie域可能是問題所在。 Chrome開發工具>資源> Cookies可以提供幫助。如果域不正確,瀏覽器將拒絕設置會話cookie。 – topek 2013-03-02 19:56:18

+0

嗨,是的,cookie在客戶端全部存在並且很好,但域屬性在節點中爲空。我將進一步調查cookieParser模塊。我可能會設置一個Ubuntu虛擬PC(第一次),看看它是否與Windows上的節點有關。謝謝 – 2013-03-02 22:13:55

回答

6

答案很簡單。我在這個星期天早上起牀特別早,爲了調試它,在我的第一杯咖啡中途突然間清楚地知道了答案,隨後的嘗試比上半年更好。

的/favicon.ico請求

我沒有處理來自瀏覽器/favicon.ico請求這對於新手節點像我這樣的疑難雜症位的復仇。每個請求後面都有一個/favicon.ico請求(至少由Chrome),以便瀏覽器可以顯示該網站的圖標。它永遠不會放棄,直到它得到一個favicon.ico。

實際會話工作得非常好,只有一個會話ID,但對/favicon.ico的請求不發送任何cookie,正是這種情況觸發了每個請求的新殭屍會話。

爲了解決這個問題,我添加了一個模塊來處理/favicon.ico請求並提供404響應。我可以輕鬆地給無情的瀏覽器一個favicon併發送,而不是使用「fs」模塊。

在使用會話模塊之前,處理/favicon.ico並結束響應而不調用next()是非常重要的!這裏的固定代碼:

var connect = require('connect'); 
var util = require("util"); 
var RedisStore = require("connect-redis")(connect); 
var http = require('http'); 

var app = connect() 
    .use(function(req, res, next) { 
    if(req.url == '/favicon.ico') { 
     serve404(res); 
    } else { 
     next(); 
    } 
    }) 
    .use(connect.cookieParser())//"elms123")) 
    .use(connect.query()) 
    .use(connect.session({ 
     secret:"elms123", 
     store:new RedisStore({prefix:'sid_'}), 
     cookie:{maxAge:60000, secure:false, domain:"gaz-node.com"} 
    })) 
    .use(function(req, res, next) { 
    var sess = req.session; 
    res.setHeader('Content-Type', 'text/html'); 
    res.write('welcome to the session demo. refresh!'); 
    if (sess.views) { 

     res.write("<p>" + util.inspect(req.cookies) + "</p>"); 
     sess.basket = sess.basket || {book1:0, book2:0, book3:0}; 
     if(req.query.buyBook1) {sess.basket.book1 ++;} 
     if(req.query.buyBook2) {sess.basket.book2 ++;} 
     if(req.query.buyBook3) {sess.basket.book3 ++;} 
     if(req.query.expiresession) {sess.cookie.maxAge=0;} 
     if(req.query.forceerror) {/*idontexist()*/throw new Error('ahhhh!');} 

     res.write('<p>views: ' + sess.views + '</p>'); 
     res.write('<ul>\ 
        <li>book1 ' + sess.basket.book1 + ' - <a href="/?buyBook1=true">Add</a></li>\ 
        <li>book2 ' + sess.basket.book2 + ' - <a href="/?buyBook2=true">Add</a></li>\ 
        <li>book3 ' + sess.basket.book3 + ' - <a href="/?buyBook3=true">Add</a></li>\ 
       </ul>\ 
       <a href="/?expiresession=true">Expire session</a>\ 
       <a href="/?forceerror=true">Force error</a>'); 
     res.write('<p>expires in: ' + (sess.cookie.maxAge/1000) + 's</p>'); 
     res.write('<p>httpOnly: ' + sess.cookie.httpOnly + '</p>'); 
     res.write('<p>path: ' + sess.cookie.path + '</p>'); 
     res.write('<p>domain: ' + sess.cookie.domain + '</p>'); 
     res.write('<p>secure: ' + sess.cookie.secure + '</p>'); 
     sess.views ++; 
    } else { 
     sess.views = 1; 
    } 

    res.end("<p>" + util.inspect(req.cookies) + "</p>"); 
    }) 
    .use(connect.errorHandler()); 
http.createServer(app).listen(3000); 

function serve404(res) { 
    res.writeHead(404, {"content-type": "text/plain"}); 
    res.end("Error : Resource not found"); 
} 
+1

甚至更​​好:.use(connect.favicon(__ dirname +'/favicon.ico')) – 2013-03-03 10:44:11

相關問題