我在启用 csrf 的情况下双重发布表单时遇到问题。
在我的设置中:移动自动完成功能会自动发布表单,但在重定向之前,如果我单击“提交”,因为所有字段都已填写,则会出现错误...但我已经登录并出现错误。如果自动填充已经发布到表单并等待页面加载,我不知道如何阻止用户单击提交按钮。
第一个表单提交成功,如果您第二次发送相同的表单,csrf 变为无效,则会发送错误消息。但是用户在后面登录了。
<form action="/login/password" method="post">
<section>
<label for="username">User Name :</label>
<input id="username" name="username" type="text" autocomplete="username" required autofocus>
</section>
<section>
<label for="current-password">Password :</label>
<input id="current-password" name="password" type="password" autocomplete="current-password" required>
</section>
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<button class="btnSign" type="submit">Sign In</button>
</form>
router.use(function (req, res, next) {
res.header("Cache-Control", "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0");
next();
});
passport.use(
new LocalStrategy(function verify(username, password, cb) {
conn.query("SELECT * FROM users WHERE username = ?", [username], function (err, row) {
if (err) {
return cb(err);
}
if (!row.length) {
return cb(null, false, {
message: "Incorrect username or password.",
});
}
//sanitize password input length. (in congfig.js)
if (locals.maxPasswordLength < password.length) {
password = password.substring(0, Math.min(password.length, locals.maxPasswordLength));
}
crypto.pbkdf2(password, row[0].salt, 310000, 64, "sha512", function (err, hashedPassword) {
if (err) {
return cb(err);
}
if (!crypto.timingSafeEqual(row[0].hashed_password, hashedPassword)) {
return cb(null, false, {
message: "Incorrect username or password.",
});
}
return cb(null, row[0]);
});
});
})
);
router.post(
"/login/password",
passport.authenticate("local", {
successReturnToOrRedirect: "/dothisonsuccess",
failureRedirect: "/login",
keepSessionInfo: false,
failureMessage: true,
})
);
router.get("/dothisonsuccess", function (req, res, next) {
if (req.cookies.getSessionReturn) {
res.clearCookie("getSessionReturn");
return res.redirect(req.cookies.getSessionReturn);
}
return res.redirect("/");
});
这不会发生在桌面上。当我使用 chrome 密码管理器自动填充字段时,所有字段都已填充,浏览器等待我单击“提交”。但在 Android 三星手机中,我单击输入字段,出现弹出窗口,然后我选择该网站的用户。然后,一旦我单击用户名填写表格,它就开始提交。我没有注意到它正在提交表单,我在选择用户后快速单击“提交”。然后就会出现错误。
我正在使用这些和许多其他的。但我认为它是自动填充发布而不会触发 chrome 中的任何内容......
"csurf": "^1.11.0",
"express": "^4.18.2",
"express-ejs-layouts": "^2.5.1",
"express-mysql-session": "^3.0.0",
"express-session": "^1.17.2",
"passport": "^0.6.0",
"passport-google-oidc": "^0.1.0",
"passport-local": "^1.0.0",
可能重复:即使登录成功,为什么在尝试访问 React 前端中的经过身份验证的路由时会收到 403 Forbidden 错误?
有
确实有一个叫做 onsubmit 的事件。
<script type="module">
window.disableSigninBtn=disableSigninBtn;
function disableSigninBtn(){
document.getElementById('btnSign').disabled = true;
}
</script>
<form action="/login/password" method="post" onsubmit="disableSigninBtn()">
这解决了双击登录按钮并在自动完成提交表单后单击登录的问题。但自动完成自动提交仍然很烦人。