Express JS提交密码后出现404错误,请求协助排查
问题
正在学习Express JS,尝试搭建一个密码验证网站:输入正确密码时展示secret.html页面,密码错误则重定向回首页。但无论输入何种密码,点击提交后均出现404错误,使用Postman测试也存在相同问题,无法定位原因。
index.html代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Secrets</title> </head> <body> <h1>Secrets</h1> <form action="/check" method="POST"> <label for="password">Password:</label> <input type="text" id="password" name="password" required> <input type="submit" value="Submit"> </form> </body> </html>
另有一个secret.html页面,将在输入正确密码时展示。
Express JS代码
import express from "express"; import bodyParser from "body-parser"; import { dirname } from "path"; import { fileURLToPath } from "url"; const __dirname = dirname(fileURLToPath(import.meta.url)); const app = express(); const port = 3000; let userIsAuthorised = false; app.use(express.json()); app.use(bodyParser.urlencoded({ extended: true })); function passwordCheck(req, res, next) { const password = req.body["password"]; if (password === "ILoveProgramming") { userIsAuthorised = true; } else { userIsAuthorised = false; } next(); } app.use(passwordCheck); app.get("/", (req, res) => { res.sendFile(__dirname + "/public/index.html"); }); app.post("/check", (req, res) => { if (userIsAuthorised) { res.sendFile(__dirname + "/public/secret.html"); } else { res.redirect("/"); } }); app.listen(port, () => { console.log(`Listening on port ${port}`); });
解决方案
你的代码存在两个核心问题,导致404错误和逻辑异常:
1. 全局中间件执行顺序错误
你通过app.use()全局挂载了passwordCheck中间件,这会导致所有请求(包括GET /)都会触发这个中间件。GET请求的req.body为空,此时password变量为undefined,不仅会错误修改全局状态,还可能在某些场景下干扰路由逻辑,间接引发404。
2. 全局变量的并发问题(非404直接原因,但必须修复)
用全局变量userIsAuthorised存储授权状态会导致多用户访问时状态混乱,比如用户A输入正确密码后,用户B即使输入错误也会看到secret页面,反之亦然。
修复步骤
- 移除全局挂载的
passwordCheck中间件,改为只在POST /check路由上使用该中间件 - 将授权状态改为请求级别的变量,存在
req对象上,保证每个请求独立 - 确认
secret.html确实存在于public目录下,路径与代码一致
修复后的Express代码:
import express from "express"; import bodyParser from "body-parser"; import { dirname } from "path"; import { fileURLToPath } from "url"; const __dirname = dirname(fileURLToPath(import.meta.url)); const app = express(); const port = 3000; app.use(bodyParser.urlencoded({ extended: true })); app.use(express.json()); function passwordCheck(req, res, next) { const password = req.body["password"]; // 将授权状态绑定到当前请求对象 req.userIsAuthorised = password === "ILoveProgramming"; next(); } app.get("/", (req, res) => { res.sendFile(__dirname + "/public/index.html"); }); // 仅在POST /check路由应用密码验证中间件 app.post("/check", passwordCheck, (req, res) => { if (req.userIsAuthorised) { res.sendFile(__dirname + "/public/secret.html"); } else { res.redirect("/"); } }); app.listen(port, () => { console.log(`Listening on port ${port}`); });
额外检查
- 启动服务后查看控制台,确认无文件找不到等报错
- 用Postman测试时,选择
x-www-form-urlencoded格式,传入password字段值再发送请求
内容的提问来源于stack exchange,提问作者Shweta Tyagi
相关产品推荐
相关产品推荐

