2012-04-15 75 views
66

我使用passport.js來處理我的nodejs + express.js應用程序的身份驗證。我設置了LocalStrategy從MongoDB獲取用戶Node.js + express.js + passport.js:在服務器重啓之間保持身份驗證

我的問題是用戶在重新啓動我的節點服務器時必須重新進行身份驗證。這是一個問題,因爲我積極發展它,不要wan't在每次重啓時登錄...(+我使用節點管理器)

這裏是我的應用程序設置:

app.configure(function(){ 
    app.use('/static', express.static(__dirname + '/static')); 
    app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(express.cookieParser()); 
    app.use(express.session({secret:'something'})); 
    app.use(passport.initialize()); 
    app.use(passport.session()); 
    app.use(app.router); 
}); 

而且會議序列化設置:

passport.serializeUser(function(user, done) { 
    done(null, user.email); 
}); 

passport.deserializeUser(function(email, done) { 
    User.findOne({email:email}, function(err, user) { 
     done(err, user); 
    }); 
}); 

我試圖解決在博客上給定的(刪除,因爲它不存在任何更多的鏈接)使用連接-的MongoDB沒有成功

app.use(express.session({ 
    secret:'something else', 
    cookie: {maxAge: 60000 * 60 * 24 * 30}, // 30 days 
     store: MongoDBStore({ 
     db: mongoose.connection.db 
    }) 
})); 

編輯另一個問題:只有一個連接應(使用一個聯接有限mongohq免費服務)

EDIT 2(如在一個版本,因爲我我的名聲是低的回答我的問題現在

這裏是解決方案,我終於找到了,用貓鼬發起連接

app.use(express.session({ 
    secret:'awesome unicorns', 
    maxAge: new Date(Date.now() + 3600000), 
    store: new MongoStore(
     {db:mongoose.connection.db}, 
     function(err){ 
      console.log(err || 'connect-mongodb setup ok'); 
     }) 
})); 
+0

只是FYI:博客鏈接重定向到一個模仿約會網站......不知道它是否是好的了。 – anthonylawson 2013-03-12 15:13:56

+1

噢,我刪除了鏈接。 – 2013-03-15 10:38:41

+11

開發人員使scuzzy約會網站。 – 2013-06-30 19:07:07

回答

54

有一個稱爲connect-mongo已經做了你需要的正是一個開源的 - MongoDB中仍然存在的會話數據

使用實例(與mongoose重用打開連接):

var session = require('express-session'); 
var MongoStore = require('connect-mongo')(session); 
var mongoose = require('mongoose'); 
mongoose.connect('mongodb://localhost/sess'); 
app.use(express.session({ 
    secret:'secret', 
    maxAge: new Date(Date.now() + 3600000), 
    store: new MongoStore(
    // Following lines of code doesn't work 
    // with the connect-mongo version 1.2.1(2016-06-20). 
    // {db:mongoose.connection.db}, 
    // function(err){ 
    //  console.log(err || 'connect-mongodb setup ok'); 
    // } 
    {mongooseConnection:mongoose.connection} 
    )   
})); 

你可以閱讀更多關於它在這裏:https://github.com/kcbanner/connect-mongo

+1

Arnaud,謝謝,我有同樣的問題。你能更清楚地瞭解db:mongoose.connection.db嗎?我不確定這意味着什麼。 – 2012-05-01 17:20:36

+0

對於遲到的反應,我很抱歉,我從墨西哥回到法國,我會在48小時後更加有效。迴應:你必須在通過mongoose初始化之後將mongo連接實例傳遞給connect-mongodb。 mongoose.connection.db是我們正在討論的實例,我們通過「db」屬性將它傳遞給connectdb。 – 2012-05-03 16:21:13

+0

你在#github上有一個工作示例嗎? – 2014-04-09 16:07:36

5

這是因爲你用MemoryStore的(默認)的會話。看看這個代碼memory.js(連接框架的一部分):

var MemoryStore = module.exports = function MemoryStore() { 
    this.sessions = {}; 
}; 

和session.js(快遞)這個片段

function session(options){ 
    /* some code */ 
    , store = options.store || new MemoryStore 
    /* some code */ 
} 

現在你應該明白,每一個服務器啓動復位MemoryStore的。爲了保留數據,你必須使用其他會話存儲。你甚至可以編寫你自己的(不應該太難),儘管Redis(見this library)可能是一個不錯的選擇(Express也支持它)。

//編輯

根據the Connect documentation如果實現getsetdestroy方法這是足以讓你的。下面的代碼應該工作:

customStore = { 
    get : function(sid, callback) { 
     // custom code, for example calling MongoDb 
    }, 
    set : function(sid, session, callback) { 
     // custom code 
    }, 
    destroy : function(sid, callback) { 
     // custom code 
    } 
}  

app.use(express.session({ 
    store: customStore 
})); 

你只需要實現通話的MongoDB(或任何其他數據庫雖然我還是建議使用nonpermament一個類似的Redis),用於存儲會話數據。還請閱讀其他實現的源代碼以獲取該想法。

+1

謝謝。正如你所看到的,我嘗試過使用connect-mongodb(和connect-mongo)而沒有成功,會話不會保存在我的數據庫中。 – 2012-04-15 20:58:13

+1

@ArnaudRinquin對不起,不知何故,我沒有看到。 :)我已經更新了答案。我並不熟悉connect-mongodb和connect-mongo(我將Redis作爲會話存儲使用貓鼬),所以我唯一給你的建議是:嘗試自己實現會話存儲。 – freakish 2012-04-15 21:40:15

+0

感謝您的幫助,但幾分鐘前我找到了解決方案,並看到您的回覆,因爲我想發佈解決方案。 – 2012-04-15 22:00:57

6

我使用連接蒙戈像這樣:

var MongoStore = require('connect-mongo'); 

var sess_conf = { 
    db: { 
    db: mydb, 
    host: localhost, 
    collection: 'usersessions' // optional, default: sessions 
    }, 
    secret: 'ioudrhgowiehgio' 
}; 

app.use(express.session({ 
    secret: sess_conf.secret, 
    maxAge: new Date(Date.now() + 3600000), 
    store: new MongoStore(sess_conf.db) 
    })); 


[...] 

// Initialize Passport! Also use passport.session() middleware, to support 
    // persistent login sessions (recommended). 
    app.use(passport.initialize()); 
    app.use(passport.session()); 
+0

謝謝,但我有一個額外的問題:我只需要一個連接在我的數據庫上,因爲我使用了mongohq免費服務(僅限一個連接)。 – 2012-04-15 22:02:42

+0

好的,這裏是使用connect-mongodb和重新使用貓鼬連接的最終的,乾淨的解決方案 – 2012-04-16 14:14:20

1

我正在使用貓鼬,我試了上面的答案中提供的代碼,它並沒有爲我工作。

Error: db object already connecting, open cannot be called multiple times 

然而,這個工作對我來說:

app.use(express.session({ 
    secret:'secret', 
    maxAge: new Date(Date.now() + 3600000), 
    store: new MongoStore({mongoose_connection:mongoose.connection}) 
})) 

注:當我做我得到這個錯誤。如果你沒有MongoStore不管出於什麼原因,你需要做的:

npm install connect-mongo --save 

則:

var MongoStore = require('connect-mongo')(express) 
2

這是probab對於有經驗的節點用戶來說是顯而易見的,但它讓我意識到:

您需要配置節點會話 - 例如,

app.use(session({secret: "this_is_secret", store: ...})); 

之前初始化護照會話 - 例如

app.use(passport.initialize()); 
app.use(passport.session()); 

如果你先調用passport.session(),它將不起作用(它不會警告你)。我認爲問題出在序列化/反序列化用戶函數,浪費了幾個小時。

1

我最終什麼事做:

var expressSession = require('express-session'); 
var redisClient = require('redis').createClient(); 
var RedisStore = require('connect-redis')(expressSession); 
... 
app.use(expressSession({ 
    resave: true, 
    saveUninitialized: true, 
    key: config.session.key, 
    secret: config.session.secret, 
    store: new RedisStore({ 
     client: redisClient, 
     host: config.db.host, 
     port: config.db.port, 
     prefix: 'my-app_', 
     disableTTL: true 
    }) 
})); 

爲我工作。

1

您需要更改您用於會話的商店。應用程序停止時,默認的'MemoryStore'不會繼續存儲會話。在github上查看快速會話,瞭解更多關於其他商店的信息,例如mongo。 (不記得名字)