MERN Stack登录功能异常求助:输入错误密码仍可登录
问题:MERN Stack登录功能异常——错误密码仍能成功登录
我发现我的MERN Stack登录功能不符合预期:即使输入错误密码仍能成功登录。我已使用bcrypt.compare进行密码校验,校验不匹配时控制台会输出错误信息,但无法阻止登录流程。以下是相关代码:
路由代码
router.post("/login", async (req, res) => { const { username, password } = req.body; const foundOne = await User.findOne({ username }); if (!foundOne) { return res.json({ message: "user does not exist" }); } const isMatch = await bcrypt.compare(password, foundOne.password); if (!isMatch) { return res.json({ message: "password incorrect" }); } const JWToken = jwt.sign({ id: foundOne._id }, secret); res.json({ JWToken, userID: foundOne._id }); });
Mongoose模型代码
const mongoose = require("mongoose"); const { Schema } = mongoose; const userSchema = new Schema({ username: { type: String, require: true, uniqle: true, }, password: { type: String, require: true, }, savedReceipes:[{type:mongoose.Schema.Types.ObjectId, ref: "recipes"}] }); module.exports = mongoose.model("User", userSchema);
React登录页面代码
import React from "react"; import { useState } from "react"; import { useCookies } from "react-cookie"; import axios from "axios"; import { useNavigate } from "react-router-dom"; const Login = () => { const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [_, setCookies] = useCookies("Jordan_token"); const navigate = useNavigate(); const handleLogin = async (event) => { event.preventDefault(); try { const result = await axios({ method: "post", url: "http://localhost:3001/user/login", data: { username, password }, headers: { // "Content-Type": "multipart/data-form, charset=UTF-8", "Content-Type": "application/json; charset=UTF-8", }, }); console.log(result); setCookies("Jordan_token", result.data.JWToken); window.localStorage.setItem("userID", result.data.userID); // window.location.pathname="/" alert("Login success, now being redirected to Homg Page"); navigate("/"); } catch (err) { console.log(err.name); console.log(err.message); } }; return ( <div className="Login"> <form> <h2>Login</h2> <div className="formDetail"> <label htmlFor="username">Username:</label> <input type="text" id="username" value={username} onChange={(event) => setUsername(event.target.value)} /> </div> <div className="formDetail"> <label htmlFor="password">Password:</label> <input type="password" id="password" value={password} onChange={(event) => setPassword(event.target.value)} autoComplete="on" /> </div> <div className="buttonDetail"> <button onClick={handleLogin}>Login</button> </div> </form> </div> ); }; export default Login;
解决方案
核心问题在于后端错误返回未设置正确的HTTP状态码,导致前端axios不会触发catch逻辑,直接执行登录成功流程。同时前端也未对返回结果做错误判断,具体修正步骤如下:
1. 修正后端路由代码:返回错误状态码
当用户不存在或密码不匹配时,应返回401 Unauthorized状态码,而非默认的200成功状态码,这样axios会将其识别为错误并进入catch块:
router.post("/login", async (req, res) => { const { username, password } = req.body; const foundOne = await User.findOne({ username }); if (!foundOne) { // 返回401状态码+错误信息 return res.status(401).json({ message: "user does not exist" }); } const isMatch = await bcrypt.compare(password, foundOne.password); if (!isMatch) { // 返回401状态码+错误信息 return res.status(401).json({ message: "password incorrect" }); } const JWToken = jwt.sign({ id: foundOne._id }, secret); res.json({ JWToken, userID: foundOne._id }); });
2. 前端代码:增加结果判断(可选但更严谨)
即使后端返回正确状态码,也可以在try块中先检查返回结果是否包含错误信息,避免意外执行登录成功逻辑:
const handleLogin = async (event) => { event.preventDefault(); try { const result = await axios({ method: "post", url: "http://localhost:3001/user/login", data: { username, password }, headers: { "Content-Type": "application/json; charset=UTF-8", }, }); // 检查是否存在错误信息 if (result.data.message) { alert(result.data.message); return; } setCookies("Jordan_token", result.data.JWToken); window.localStorage.setItem("userID", result.data.userID); alert("Login success, now being redirected to Home Page"); navigate("/"); } catch (err) { // 捕获后端返回的错误信息 alert(err.response?.data?.message || "Login failed"); console.log(err.name); console.log(err.message); } };
3. 修正Mongoose模型的拼写错误(非当前问题核心,但需修复)
模型中存在两处拼写错误,可能导致后续数据验证问题:
require→requireduniqle→uniquesavedReceipes→savedRecipes(拼写规范优化)
修正后的模型代码:
const mongoose = require("mongoose"); const { Schema } = mongoose; const userSchema = new Schema({ username: { type: String, required: true, unique: true, }, password: { type: String, required: true, }, savedRecipes:[{type:mongoose.Schema.Types.ObjectId, ref: "recipes"}] }); module.exports = mongoose.model("User", userSchema);
内容的提问来源于stack exchange,提问作者ksyu1113
相关产品推荐
相关产品推荐

