Я предполагаю, что это является частью той же проблемы, что и здесь , где реальная проблема заключается в том, что вы хотите принудительно выполнить аутентификацию перед определенными маршрутами администратора, а затем после успешной аутентификации вы хотите перенаправить обратно на маршрут администратора, который был первоначально запрошен, и когда ваш обработчик Express обрабатывает этот маршрут администратора, он должен знать, что теперь ему не нужно принудительно выполнять аутентификацию, потому что аутентификация была только что выполнена.
Мое предложение будет используйте для этого сеанс Express.
Вот общие шаги:
В ваших маршрутах /admin
вы создаете промежуточное ПО checkAdminPassword()
, которое проверяет Посмотрите, был ли пароль проверен совсем недавно (подробнее об этом позже). Если нет, он перенаправляет на страницу паролей и предварительно заполняет эту форму страницы паролей в скрытом поле, оригинальном желаемом URL-адресе назначения.
В маршруте обработки пароля вы проверяете пароль и вы устанавливаете в объекте сеанса express время проверки маршрута.
Затем вы используете исходное назначение пользователя (которое было включено в форму пароля в скрытом поле) для после успешной проверки пароля перенаправьте пользователя обратно к его исходному месту назначения.
Затем, когда маршрут /admin
снова будет достигнут, он вызывает промежуточное ПО checkAdminPassword()
. На этот раз это промежуточное ПО просматривает объект сеанса и видит, что пароль был только что подтвержден, несколько секунд go. Поскольку он был только что подтвержден, он не запрашивает снова и пропускает пользователя по маршруту администратора.
Вот примеры кода в нескольких из этих частей. Здесь, когда это совпадает, он устанавливает проверку в сеансе и устанавливает текущее время, а затем перенаправляет на redirectTarget (скрытое поле из формы).
// Validate password, admin re-enter password to get access to /admin routes
router.post('/validate-password', async (req, res, next) => {
const password = req.body.password;
const match = await passwordController.comparePassword(password, req.user.password);
console.log(password);
if (match) {
// set the time of last password verification
req.session.passwordVerifiedTime = Date.now();
res.redirect(req.body.redirectTarget).
} else {
// return res.render('changePassword', {role_id: req.user.role_id});
req.session.passwordVerifiedTime = 0;
// pass the target for redirection after successful password so this template
// can insert that in a hidden field in the password form
return res.render('validatePassword', {message: 'Wrong password', target: req.session.redirectAfterAuthUrl});
}
});
Тогда я бы избавился от router.all('/admin/*', ...)
маршрут, так как вам это не нужно. На любом маршруте /admin
, для которого требуется дополнительная проверка, вы можете просто добавить промежуточное программное обеспечение к этому маршруту или, если у вас есть целый маршрут этих маршрутов, вы можете добавить промежуточное программное обеспечение только к маршрутизатору.
router.get('/admin/register', checkAdminPassword, (req, res) => {
res.render('register', {message: req.flash('message'), role_id: req.user.role_id})
});
function checkAdminPassword(req, res, next) {
const adminPasswordExpiration = 30 * 1000; // 30 seconds, you can set it to whatever you want
const now = Date.now();
if (req.session.passwordVerifiedTime && (now - req.session.passwordverified < adminPasswordExpiration)) {
next();
} else {
// admin password verification either not set or expired
// remember our desired target location
req.session.redirectAfterAuthUrl = req.url;
res.redirect("/validate-password");
}
}