我有一个登录系统,用户将数据发布到/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('/')
}
})
}
});
所以它保存数据并重定向到索引,但每次用户去索引页它显示欢迎信息,它显然这样做,因为变量仍然是定义的,所以我的目标是改变变量太空后,他们登录和欢迎信息显示一次。
我试过:
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的自动保存会话将尝试在您发送res.redirect()
之后保存会话,但是发送res.redirect()
会告诉浏览器立即请求另一个页面,因此您在会话的自动保存和来自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('/')
});
}
})
}
});