2015-09-13 3 views
0

Я столкнулся с проблемой, что люди на моем веб-сайте могут дважды отправить форму. Это не проблема со стороны базы данных, так как записи сохраняются с помощью проверки на стороне сервера. Тем не менее, важно ли я аннулировать любые дополнительные запросы, чтобы пользователи не получали двойную зарплату (так как оплата происходит до создания учетной записи). Я бы предпочел отказаться от запроса полностью, а не перенаправлять, потому что он действительно разрушит UX, в то время как отказ от запроса просто заставит процесс «казаться» дольше, что является лучшим компромиссом.Как предотвратить двойные формы отправки в ExpressJS

Чтобы устранить проблему, я также использую шаблон post-redirect-get, но он не решает эту проблему, которая на самом деле является самой важной проблемой, поскольку она является наиболее распространенной. Реализация клиентского решения будет выполнена для чистоты пользовательского интерфейса, но я не могу доверять пользователю, чтобы не отключать 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, и в результате он не будет блокировать любые запросы для нескольких нажатий, пока все не настигнет.

Что я здесь делаю неправильно и как его исправить?

EDIT: Rate-ограничив POST к/создать кажется возможность, хотя это не похоже, решение реального я полагаю. Это может сработать.

ответ

1

Вы должны быть в состоянии упростить его просто обработки флага с тем промежуточным слоем, например, так:

var protect_route = function(req, res, next){ 
    if(!req.session.processing){ 
    req.session.processing = true; // set flag 
    next(); // continue in route chain 
    } else { 
    res.status(400).send() // end request here with 400 status code, drop everything 
    } 
} 

var unlock_route = function(req, res, next){ 
    req.session.processing = false; // unset flag 
    next(); 
}; 
+0

К сожалению, это страдает от тех же проблем. Вымывание кнопки создает несколько запросов. Узел не обрабатывает эти синхронно, поэтому промежуточное ПО не «реализует» его до тех пор, пока запрос не будет выполнен. Вы можете это увидеть сами, разместив инструкции console.log в каждой из функций промежуточного программного обеспечения, а затем замяв кнопку отправки, пока она не блокируется. – Steve

+0

Перед тем, как вы позвоните дальше, заставьте сеанс сохранить. Обычно это делается в конце запроса. 'req.session.save (function() {next()})' - все еще не идеально, но если у вас есть многолетние асинхронные вещи, которые происходят после этого, это должно помочь свести к минимуму состояние гонки. – furydevoid

Смежные вопросы