2012-06-05 63 views
3

我有以下路線,基本上從登錄表單發佈的行爲。問題是,當登錄成功時(找到成員並且密碼匹配),member._id不會存儲在會話中。會話沒有存儲在Express的Node.js

我的路線:

app.post('/signin', function(req, res) { 
    Member.findOne({username: req.body.username}, function(error, member) { 
     var matchPassword = crypto.createHmac('sha1', member.salt).update(req.body.password).digest('hex'); 
     if(member.password == matchPassword) { 
      req.session.member_id = member._id; 
      res.redirect('/' + member.username); 
     } 
    }); 
    res.redirect('/'); 
}); 

我得到控制檯以下錯誤,當這條路被觸發:

node.js:134 
     throw e; // process.nextTick error, or 'error' event on first tick 
     ^
Error: Can't set headers after they are sent. 
    at ServerResponse.<anonymous> (http.js:527:11) 
    at ServerResponse.setHeader (/Users/admin/Node Projects/sandboxProject/node_modules/express/node_modules/connect/lib/patch.js:62:20) 
    at ServerResponse.header (/Users/admin/Node Projects/sandboxProject/node_modules/express/lib/response.js:280:8) 
    at ServerResponse.redirect (/Users/admin/Node Projects/sandboxProject/node_modules/express/lib/response.js:413:10) 
    at Promise.<anonymous> (/Users/admin/Node Projects/sandboxProject/app.js:109:8) 
    at Promise.<anonymous> (/Users/admin/Node Projects/sandboxProject/node_modules/mongoose/lib/promise.js:120:8) 
    at Promise.<anonymous> (events.js:64:17) 
    at Promise.emit (/Users/admin/Node Projects/sandboxProject/node_modules/mongoose/lib/promise.js:59:38) 
    at Promise.complete (/Users/admin/Node Projects/sandboxProject/node_modules/mongoose/lib/promise.js:70:20) 
    at /Users/admin/Node Projects/sandboxProject/node_modules/mongoose/lib/query.js:1087:15 

這似乎是它沒有像「res.redirect(」 /'+ member.username);「在「req.session.member_id = member._id;」之後。這是因爲Mongoose findOne回調函數的異步性質嗎?我嘗試從回調中刪除res.redirect,但會話數據不存儲,當我把它留在那裏,我得到「頭已發送」錯誤。

我的配置:

app.configure(function(){ 
    app.set('views', __dirname + '/views'); 
    app.set('view engine', 'jade'); 
    app.use(express.cookieParser()); 
    app.use(express.session({ secret: "blahblah" })); 
    app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(app.router); 
    app.use(express.static(__dirname + '/public')); 
}); 
+0

有固定的問題 - 原來,這是很簡單,需要一點點常識! 由於來自Mongoose的回調是異步的,並在「res.redirect('/');」之後觸發會話存儲在我以前的路線的破碎版本。所有你需要做的就是處理回調中的失敗,並放棄「res.redirect('/');」從路由回調結束。哎呀! –

+0

如果下面的解決方案有效,您能選擇一個作爲正確的答案,以幫助其他人解決同樣的問題嗎? – Brandon

回答

8

我也有類似的問題。儘管我的問題是,當我從會話中刪除某些內容時,例如delete req.session.user,在重新加載和節點應用程序重新啓動後,它仍會在那裏。它只會在req.session.destroy()後消失。

我看着Node的會話middleware docs,發現他們有一個Session#save()方法。所以我在會話對象操作之後做了req.session.save(),它確實解決了我的問題。嘗試一下,看看它是否修復了你的問題。

+0

雖然這個答案指出我在正確的方向,我會明確說明'req.session.save()'是一個以回調爲參數的異步函數。所以任何依賴於保存數據的東西都應該在回調中執行。當使用內存存儲進行開發時,這通常並不明顯,並且「及時」發生。 –

4

問題是Member.findOne是異步的。當它的回調執行時,res.redirect('/')已經執行,它設置適當的HTTP響應頭。您無法通過HTTP規則兩次發送標頭,因此錯誤Can't set headers after they are sent.

您可能希望將redirect('/')移動到您的密碼匹配的else塊中。