我遇到过网站上的人可以双重提交表单的问题。这不是数据库方面的问题,因为记录是通过服务器端验证保存的。但是,重要的是我使任何其他请求无效,以便用户不会被双重收费(因为收费发生在帐户之前)。我宁愿完全放弃请求,而不是重定向,因为它会破坏用户体验,而删除请求只会使进程“显得”更长,这是一个更好的妥协。
为了清理,我也在使用post-redirect-get模式,但它并没有解决这个问题,这实际上是最关键的问题,因为它是最常见的。实现客户端解决方案将是为了清洁UI,但我不能相信用户不禁用javascript或以某种方式篡改它。
我有一个使用库csurf
的中间件解决方案,但不太有效。
var protect_route = function(req, res, next){
if(!req.session.unique_requests){
req.session.unique_requests = [];
}
var found = _.find(req.session.unique_requests, function(token){
return token === req.body._csrf;
});
if(!found){
req.session.unique_requests.push(req.body._csrf);
next();
} else {
next('route'); //drop the post, and skip anything else.
}
};
var unlock_route = function(req, res, next){
req.session.unique_requests = _.without(req.session.unique_requests, req.body._csrf);
};
我将它附加到我的路线上:
router.post('/create', protect_route, function(req, res){
// If it makes it in here, the route is protected and the
// request wasn't dropped.
});
router.get('/review', unlock_route, function(req, res){
// The form will once again be able to be submitted.
});
不幸的是,即使中间件被调用,如果我混搭创建按钮,它会触发大量请求,每个请求都会尝试将令牌推送到unique_requests
,结果是它不会阻止任何推送请求,直到一切都赶上来。
我在这里做错了什么,我该如何解决?
编辑:将POST限制为/ create似乎是一种可能,但我认为它似乎不像真正的解决方案。它可能会奏效。
答案 0 :(得分:0)
by using a simple session counter and set it as needed in this example of
adding a role name single field string unique in schema definition
counter field name is rolesubmitcounter
///////////////////////////////////////////
router.get('/add',ensureAuthenticated, function(req,res){
req.session.rolesubmitcounter=0;
res.render('roles/role_add',{
title:"add role",
nrole: {roleName:""}
});
});
// Add Submit POST Route
router.post('/add', ensureAuthenticated, function(req, res){
if (req.session.rolesubmitcounter ===0){
var tt1 =req.body.roleName.toString().trim();
if(tt1==="".trim()){
req.session.rolesubmitcounter=0;
req.flash('danger','Role not..added.....may be empty fields......');
res.render('roles/role_add', {
title:'Add role',
nrole: {roleName:req.body.roleName}
});
}
else{
///////////////////////////////////////
req.session.rolesubmitcounter = 1;
let nrole = new Role();
nrole.roleName = req.body.roleName.toLowerCase().trim();
///////////////////////////////////////////
nrole.save(function(err){
if(err){
req.session.rolesubmitcounter=0;
req.flash('danger','Role not..added.....may be duplicate key..');
res.render('roles/role_add',{
nrole: nrole
});
} else {
req.flash('success','Role Added');
res.redirect('/roles/roleindex');
}
});
}
}else{
req.flash('danger','double submission Detected.....click once slowly');
res.redirect('/roles/roleindex');
}
});