重定向后NodeJS更改会话变量

NodeJS change session variable after redirect

我有一个登录系统,用户将数据发布到 /login 路由,如果登录正确,它会保存数据。

router.post('/login', function(req, res, next) {
  if(req.method == 'POST') {
    const username = req.body.username;
    const password = req.body.password;
    sql.query('SELECT * FROM `users` WHERE `username` = "'+username+'"', function(err, results) {
      if(err) { 
        req.session.message = {status: 'danger', message: 'Failed to login, check password.'}
        res.redirect('/')
      } else if (results.length != 0) {
        const passw = results[0].password;
        bcrypt.compare(password, passw, function(err, result) {
          if(result) {
            req.session.loggedin = true;
            req.session.data = results[0];
            req.session.message = {status: 'success', message: `Welcome back, ${username}.`}
            req.session.save(function(err) {
                res.redirect(req.headers.referer);
            })
          } else {
            req.session.message = {status: 'danger', message: 'Failed to login, check password.'}
            res.redirect('/')
          }
        });
      } else {
        req.session.message = {status: 'danger', message: 'Failed to login, check username.'}
        res.redirect('/')
      }
    })
  }
});

所以它保存数据并重定向到索引但是每次用户进入索引页面时它都会显示欢迎消息,显然这样做是因为变量仍然被定义所以我的目标是在之后将该变量更改为 null他们登录后欢迎消息出现一次。

我试过:

delete req.session.message

但这只是在传递给下一个请求之前删除变量。

我如何显示消息:

<script type="text/javascript">
   var message = JSON.parse('<%- JSON.stringify(message) %>');
   $(document).ready(function(){
      if(message != null) {
         $('.toast').addClass('bg-' + message.status);
         $('.toast-body').html(message.message)
         $(".toast").toast('show');
      }
   });        
</script>

我如何渲染数据:

if(req.session.loggedin) {
    res.render('index', {
        loggedin: true,
        data: req.session.data,
        message: req.session.message
    });
} else {
    res.render('index', {
        loggedin: false,
        data: null,
        message: req.session.message
  });
}

呈现包含消息的页面后,您需要从会话中清除消息:

if (req.session.loggedin) {
    res.render('index', {
        loggedin: true,
        data: req.session.data,
        message: req.session.message
    });
} else {
    res.render('index', {
        loggedin: false,
        data: null,
        message: req.session.message
    });
}
req.session.message = null;
req.session.save();

并且,为避免在重定向和保存会话之间出现任何竞争条件,在手动保存会话之前不应重定向。问题是 express-session 依赖会话的 auto-save 将在您发送 res.redirect() 后尝试保存会话,但发送 res.redirect() 会告诉浏览器立即请求另一个页面,以便您在会话的 auto-save 和来自 res.redirect() 的新传入请求之间设置竞争。你不想要那场比赛。您希望在发出重定向之前确保会话已保存。所以,我将 res.redirect() 放在 req.session.save() 回调中以避免任何可能的竞争条件:

router.post('/login', function(req, res, next) {
  if(req.method == 'POST') {
    const username = req.body.username;
    const password = req.body.password;
    sql.query('SELECT * FROM `users` WHERE `username` = "'+username+'"', function(err, results) {
      if(err) { 
        req.session.message = {status: 'danger', message: 'Failed to login, check password.'}
        res.redirect('/')
      } else if (results.length != 0) {
        const passw = results[0].password;
        bcrypt.compare(password, passw, function(err, result) {
          if(result) {
            req.session.loggedin = true;
            req.session.data = results[0];
            req.session.message = {status: 'success', message: `Welcome back, ${username}.`}
            req.session.save(function(err) {
                res.redirect(req.headers.referer);
            })
          } else {
            req.session.message = {status: 'danger', message: 'Failed to login, check password.'}
            req.session.save(() => {
                res.redirect('/')
            });
          }
        });
      } else {
        req.session.message = {status: 'danger', message: 'Failed to login, check username.'}
        req.session.save(() => {
            res.redirect('/')
        });
      }
    })
  }
});