2012-03-13 62 views
2

我已經在我的Express/Mongoose網絡應用程序中成功實施了Passport-local,但是我很難弄清楚如何正確呈現失敗的登錄消息。如何使用Express和PassportJS正確報告無效登錄?

這裏是我的登錄路由:

app.get('/login', function(req, res) { 
    res.render('user/login', { 
    }); 
}); 

有了這樣的路線,我怎麼報告無效登錄?如果登錄成功,它會將id/username寫入req.user對象,但這對"GET /login"路由沒有幫助,因爲如果成功,您將被重定向到您要去的頁面。

這意味着req.user將始終爲undefined當您GET登錄頁面。

我想寫出一條信息,說'喲,無效登錄!'當以下事情發生時:

  1. 該用戶不存在。
  2. 提供的密碼不匹配,但用戶存在。

我可能想根據發生的情況輸出不同的消息。

當我實現了LocalStrategy我用這個代碼:

passport.use(new LocalStrategy({ 
    usernameField: 'email' 
}, 
function(email, password, fn) { 
    User.findOne({'login.email': email}, function(err, user) { 
    // Error was thrown. 
    if (err) { 
     return fn(err); 
    } 

    // User does not exist. 
    if (!user) { 
     return fn(null, false); 
    } 

    // Passwords do not match. 
    if (user.login.password != utility.encryptString(user.login.salt + password)) { 
     return fn(null, false); 
    } 

    // Everything is good. 
    return fn(null, user); 
    }); 
} 
)); 

正如你可以看到有一些問題,但是這是PassportJS的作者是如何建立自己的應用程序。我們應該如何訪問該戰略的回報?

如果它引發錯誤,我應該怎麼稱呼才能訪問err

謝謝。

回答

10

您可以使用自定義回調或中間件功能進行更多控制。有關示例,請參閱指南的Authentication部分。

例如,定製的回調可能看起來像:

app.get('/login', function(req,res,next) { 
    passport.authenticate('local', function(err,user) { 
      if(!user) res.send('Sorry, you\'re not logged in correctly.'); 
      if(user) res.send('Skeet skeet!'); 
    })(req,res,next); 
}); 

或者,你總是可以重定向兩種反應:

app.get('/login', 
    passport.authenticate('local', { successRedirect: '/winner', 
            failureRedirect:'/loser' })); 

或者用簡單的中間件重定向失敗:

app.get('/login', ensureAuthenticated, 
    function(req,res) { 
       // successful auth 
       // do something for-the-win 
    } 
); 

    // reusable middleware 
    function ensureAuthenticated(req,res,next) { 
     if(req.isAuthenticated()) {return next();} 
     res.redirect('/login/again'); // if failed... 
    } 
+0

很好,自定義回調方法看起來像它會工作。謝謝。 這兩種替代解決方案如何做同樣的事情呢?您不會在POST請求上執行成功/失敗重定向示例嗎?這就是我在做的事。 而第二個替代方案只是強制登錄訪問頁面的標準方式?就像,這是你想放在你想控制訪問的頁面上(用戶配置文件等)。 我打算將您標記爲自定義回調的答案。 – AntelopeSalad 2012-03-14 11:44:17

+0

我把你的問題說成是「我怎樣才能迴應認證成功或失敗?」,這三種方法是不同的。對於替代品,您只需將客戶端發送到不同的路由來處理響應......因爲我不知道您實施的具體情況,所以由您決定什麼是最好的。是的,選項3是爲需要認證的頁面強制執行認證的好方法。 – 2012-03-14 17:30:36

17

在最新版本的護照,我已經添加了對Flash消息的支持,這可以讓你輕鬆地做你正在問的問題。

您現在可以向done提供第三個參數,其中可以包含失敗消息。例如:

if (user.login.password != utility.encryptString(user.login.salt + password)) { 
    return fn(null, false, { message: 'yo, invalid login!' }); 
} 

然後,設置failureFlashtrue作爲一個選項authenticate()

passport.authenticate('local', { successRedirect: '/', 
           failureRedirect: '/login', 
           failureFlash: true }); 

在這種情況下,如果認證失敗,該消息將在閃光燈設置,隨時爲您呈現它,當您再次顯示登錄頁面。

自定義回調也非常好。內置的選項只是簡化了完成常見任務。

另外,我很好奇:你提到樣品存在問題。你認爲應該改進什麼?我想盡可能地提供例子。謝謝!

(有關更多詳細信息,請參閱第012號上的comment)。

+0

故障閃光燈使其更容易。但我注意到,任何傳遞給'done'或OP的'fn'的'err'對於這項工作必須爲空或假 - 花了我一分鐘的時間才意識到這一點。 – JohnnyCoder 2014-02-09 18:51:55