2016-04-15 104 views
6

出於安全原因,我們創建用戶並向其發送臨時生成的密碼。在繼續導航受保護頁面之前,用戶首次登錄時應更改其密碼。護照本地臨時密碼(首次登錄時更改)

我正在使用運行護照本地模塊的快遞/節點網站。註冊,登錄用戶全部工作。但是我有點迷失在用戶在第一次登錄時更改密碼的最佳做法。

我的想法是做到以下幾點:

/* POST login page. */ 
router.post('/login', function(req, res, next) { 
    passport.authenticate('local', { successRedirect: '/dashboard/users', 
    failureRedirect: 'pages/login'}, function(err, user, info) { 
    if(err) { 
     console.log('') 
     return res.render('pages/login', {title: 'Login', error: err.message}); 
    } 

    if(!user) { 
     return res.render('pages/login', {title: 'Login', error: info.message}); 
    } 
    return req.logIn(user, function(err) { 
     if(err) { 
     return res.render('pages/login', {title: 'Login', error: err.message}); 
     } else if (user.firstLogin) { 
     return res.redirect('/change-password'); // <- First login 
     } else { 
     return res.redirect('/dashboard/users'); 
     } 
    }); 
    })(req, res, next); 
}); 

正如你可以看到我有一個簡單的布爾(TINYINT 0-1)在我的數據庫設置(默認爲1)。之後我會設置一個post方法,在成功修改之後,布爾值將被設置爲0.

這是一個正確的方法('a'而不是'':p)?安全性如何?

回答

4

肯定是a正確的方法。我會說它非常適合你的需求。我個人喜歡數據庫字段的用法如何直接反映它背後的業務邏輯。

替代品,雖然我是你的解決方案的風扇,可以是:

添加lastLogin日期字段到您的數據庫默認爲NULL。這會在用戶登錄時存儲日期時間標記。如果用戶曾經登錄過,則可以將其用作隱式檢查。我個人更喜歡爲他們的目的有明確的列(比如你正在處理你的firstLogin列),因爲應用程序的列和業務邏輯的目的非常明確。

另一種方法是存儲,當用戶有最近更新他的密碼即lastPasswordChange默認爲NULL爲新用戶。與上述相同的推理。如果您希望您的用戶每天更改密碼,可能會很有用。

安全性說我會說這是堅實的。只要您的firstLogin字段默認爲1,那麼在首次登錄時,新用戶將無法跳過密碼更改。

然而,當用戶更新自己的密碼,請務必在同一個查詢執行事務中兩個查詢更新該firstLogin領域。通過這種方式,您將始終確保密碼firstLogin字段已更改。如果由於某種原因,任何一個查詢都會失敗,您將有一個用戶已經更改了密碼,並被要求/強制再次更改密碼,或者擁有隨機生成密碼的用戶不要求更改密碼。 在相同的查詢中執行此操作將確保兩者都一致,或兩者都不會同時更新。在事務內部執行操作時,您可以選擇在任一查詢失敗時選擇失敗/回滾事務。

在另一方面,你的代碼可以這樣寫的(包括你的路,這是正確的,它只是一個偏好和視覺的物質):

/* POST login page. */ 
router.post('/login', function(req, res, next) { 
    passport.authenticate('local', { 
     successRedirect: '/dashboard/users', 
     failureRedirect: 'pages/login' 
    }, function(err, user, info) { 
     if(err) { 
      console.log('') 
      return res.render('pages/login', {title: 'Login', error: err.message}); 
     } 

     if(!user) { 
      return res.render('pages/login', {title: 'Login', error: info.message}); 
     } 
     return req.logIn(user, function(err) { 
      if(err) { 
       return res.render('pages/login', {title: 'Login', error: err.message}); 
      } 

      // Using if/else if/else makes no difference since if the first if is executed 
      // in both cases nothing else will execute due to if/else or the return. 
      // In case the above statement resolves to `false` the effect wills till be the same 

      if (user.firstLogin) { 
       return res.redirect('/change-password'); // <- First login 
      } 
      // The else is not necessary due to the return in the line above. 
      return res.redirect('/dashboard/users'); 
     }); 
    })(req, res, next); 
}); 

如果您想更具體的答案要麼問題,我需要一個更具體的問題。

+1

對不起,遲到的接受。謝謝你的回覆,幫助我很多。 – Goowik

1

將「檢查首次登錄」邏輯移動到單獨的中間件中執行所有「登錄路由」可能是一件好事。

根據上面的建議,用戶可以簡單地在重定向後離開/更改密碼?

+0

我不介意用戶離開頁面,但只要他想再次登錄:他將被再次要求更改密碼。我可能會記錄整個情況來檢查這一點。 – Goowik

相關問題