2012-06-30 30 views
26

我已經有了Passport安裝程序來驗證存儲在mongodb中的用戶。似乎工作正常:身份驗證成功/失敗並會話變量得到設置。但是,獲得護照檢查會話失敗。有些東西似乎是非常錯誤的,我添加到deserializeUser回調中的console.log語句永遠不會看到白天的光芒。我認爲我的問題與deserializeUser從未被調用有關。任何人都可以診斷我的失誤?PassportJS反序列化用戶從來沒有叫

// Passport configuration 
passport.serializeUser(function(user, cb){ cb(null, user.id) }); 
passport.deserializeUser(function(uid, cb){ 
    console.log("Trying to deserialize user: "+uid); 
    User.findById(uid, function(err, user){ 
    cb(err, user); 
    }); 
}); 
// auth strategy function 
passport.use(new LocalStrategy({usernameField: 'email'}, 
    function(email, pass, done){ 
    User.findOne({email: email}, function (err, user) { 
     if (err) 
     return done(err); 
     if (!user) 
     return done(null, false, {message: "Couldn't find user"}); 
     var crypted = bcrypt.hashSync(pass, user.salt); 
     if(user.hashpass != crypted) 
     return done(null, false, {message: "Bad password"}); 
     return done(null, user); 
    }); 
    } 
)); 

passport.CreateSession = function (req, res, next) { 
    passport.authenticate('local', function(err, user, info){ 
    if(err || !user) 
     return res.json({status: "Failure: "+err}); 
    req.logIn(user, function (err){ 
     if(err) 
     return res.json({status: "Failure: "+err}); 
     return res.json({status: "Authenticated"}); 
    }); 
    })(req, res, next); 
}; 

在app.js如下:

app.post('/session', passport.CreateSession); // restify better 
app.del('/session', passport.DestroySession); 
app.get('/images', passport.CheckSession, routes.images); 

回答

9

你有use()倒是passport.session()中間件?就像這個例子:

https://github.com/jaredhanson/passport-local/blob/v1.0.0/examples/login/app.js#L91

這就是恢復對話,並呼籲deserializeUser,所以它聽起來像可能會丟失。

+0

Jared - 感謝您的幫助。是的,我有app.use(passport.session());在app.js –

+0

這是節點0.8.0,表達2.5.10,和最新的護照,順便說一句。 –

+0

嗯,我假設你有正確的會議設置和持續?如果是這樣,我沒有看到任何明顯的。以下是我的建議:1.嘗試在節點0.6.x下運行,以查看0.8中是否存在不兼容問題。 2.發佈可運行的複製粘貼要點,然後運行它並查看我能找到的內容。 –

-1
passport.serializeUser(
    function(user, done){ 
     done(null, user.id); 
}); 

passport.deserializeUser(
    function(id, done){ 
     User.findById(id, function(err, user){ 
      if(err){ 
       done(err); 
      } 
      done(null, user); 
     }); 
}); 

**> try this one** 
21

對於別人誰是有這個問題,看看這個:

app.use(session({ 
    secret: 'something', 
    cookie: { 
     secure: true 
    }})); 

如果你有cookie.secure設置爲true,你沒有使用SSL(即HTTPS協議),那麼帶會話ID的cookie不會返回給瀏覽器,並且所有內容都會以靜默方式失敗。去掉這個標誌解決了我的問題 - 花了好幾個小時才能認識到這一點!

+3

Dave之下/之後,會話在這裏是「快速會話」嗎?你能說清楚嗎? –

+1

這應該是正確答案 –

+0

這對我來說是個問題,花了2個工作日才找到這個答案... 謝謝! –

1

我一整天都遇到同樣的問題。我設置了一個自定義回調來執行授權(例如在http://passportjs.org/guide/authenticate/的底部)。它看起來像Passport預處理所有的請求對象之前,他們甚至擊中了其他中間件(根據我寫的一些日誌語句)。作爲預處理的一部分,它將反序列化的用戶信息放入request.user對象中。不幸的是,passport.authenticate('local',callback)的默認行爲似乎是忽略任何會話或cookie數據,而是假設用戶名和密碼正在請求對象中發送。我所做的解決這個問題的方法是首先檢查request.user對象,如果它存在,這意味着Passport已經完成了它的預處理,然後我可以直接調用login。這裏是我的授權功能,這是我在的地方passport.authenticate的使用(「本地」):

function doAuth(request, response, next) 
{ 

if (request.user) { 
    request.logIn(request.user, function (err) { 
     if (err) { 
      console.log(err); 
      response.status(500).json({message: 
        "Login failed. Auth worked. Nonsense"}); 
      return; 
     } 
     console.log("doAuth: Everything worked."); 
     next(); 
    }); 
    return; 
} 

passport.authenticate('local', function(err, user, info) { 
    if (err) { 
     response.status(500).json({message: "Boo Passport!"}); 
     return; //go no further 
     //until I figure out what errors can get thrown 
    } 
     console.log("Authentication failed. Here is my error:"); 
     console.log(err); 
     console.log("Here is my info:"); 
     console.log(info); 
     response.status(500).json({message: "Authentication failed."}); 
     return; 
    } 
    request.logIn(user, function(err) { 
     if (err) { 
     console.log("Login failed. This is the error message:"); 
     console.log(err); 
     response.status(500).json({message:"Login failed."}); 
      return; 
     } 
     console.log("doAuth: Everything worked. I don't believe it."); 

     next(); 
    }); 
})(request, response, next); 

} 
+0

你的解釋對我很有幫助!我沒有應用你的解決方案,但你指出了問題,但是:D –

14

如果您使用的是authenticate回調,當你與你需要登錄用戶手動護照驗證。它不會被要求你。

passport.authenticate('local', function (err, user) { 
    req.logIn(user, function (err) { // <-- Log user in 
     return res.redirect('/'); 
    }); 
})(req, res); 
+0

從護照的文檔:'注意:passport.au thenticate()中間件自動調用req.login()。此功能主要用於用戶註冊時,在此期間可以調用req.login()以自動登錄新註冊的用戶。# – jbodily

+2

您可能想重新檢查一下,如果您正在進行auth手動,它將不會被調用。 – Rick

+2

裏克的回答是正確的。我花了好幾個小時弄清楚了...... – BlackSoil

-1

確保的app.use(express.static(path.join(__dirname, 'public')));停留下面app.use(require('express-session')

+0

爲什麼?這個命令對於這個問題並不重要 - deserializeUser'也不會被調用,而且,你可以在每個資產請求上獲得數據庫查詢。你確定你需要爲你的每個'styles.css'查詢session嗎? – Green

0

今天我面臨着同樣的問題,該行代碼,並在我的情況的原因是客戶端如何使API調用。而下面的方法幫助我克服的問題:

const doFetch(url, method = 'GET', body) { 
    const headers = new Headers(); 
    headers.append('Content-Type', 'application/json'); 
    headers.append('Accept', 'application/json'); 
    headers.append('Cache', 'no-cache'); 
    const params = { 
    method, headers, 
    credentials: 'include' // The cookie must be sent! 
    } 
    if(body) { 
    params.body = body; 
    } 
    return fetch(url, params); 
} 

在此之後,deserializeUser開始被正常調用。