护照本地临时密码(首次登录时更改)

问题描述:

出于安全原因,我们创建用户并向其发送临时生成的密码。在继续导航受保护页面之前,用户首次登录时应更改其密码。护照本地临时密码(首次登录时更改)

我正在使用运行护照本地模块的快递/节点网站。注册,登录用户全部工作。但是我有点迷失在用户在第一次登录时更改密码的最佳做法。

我的想法是做到以下几点:

/* 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)?安全性如何?

肯定是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

将“检查首次登录”逻辑移动到单独的中间件中执行所有“登录路由”可能是一件好事。

根据上面的建议,用户可以简单地在重定向后离开/更改密码?

+0

我不介意用户离开页面,但只要他想再次登录:他将被再次要求更改密码。我可能会记录整个情况来检查这一点。 – Goowik