Node.js+MongoDB前端登录报400凭证无效问题求助
登录接口返回400 Invalid credentials 问题排查
问题根因
共3处直接导致报错的代码问题:
- 前端表单字段名配置错误:密码输入框的
name属性写错为Passowrd(首字母大写+单词拼写错误),和后端约定接收的password字段名不匹配。前端handleChange方法通过e.target.name更新表单状态,这会导致输入密码时,状态对象里新增了Passowrd字段,初始定义的password字段始终为空字符串,最终提交给后端的请求体中没有正确的密码值。 - 前后端数据类型不匹配:前端表单输入获取的所有值都是字符串类型,但MongoDB Schema中将
password定义为Number类型,数据库中存储的是数字类型密码。后端密码比对使用严格不等运算符!==,字符串格式的密码和数字格式的密码类型不同,永远无法通过校验。 - 后端JWT生成代码存在语法错误:
jwt.sign的回调函数没有包裹大括号,哪怕账号密码校验通过,代码运行到此处也会抛出语法异常,无法正常返回token。
修复方案
1. 修复前端登录页代码
修正密码输入框的name属性为正确值,同时建议将密码输入框type改为password避免明文显示:
// 原错误代码 // <input type="text" className="form-control" placeholder='Passowrd' name="Passowrd" onChange={handleChange} /> // 修正后代码 <input type="password" className="form-control" placeholder='Password' name="password" onChange={handleChange} />
2. 修复后端登录接口代码
补全JWT回调的大括号,同时在比对密码时做类型统一转换:
router.post('/login', async(req,res) =>{ try { const {email,password} =req.body; let exist = await Auth.findOne({email}) if(!exist){ return res.status(400).json("User Not Found"); } // 将前端传入的字符串密码转为数字,和数据库存储的数字类型密码做比对 if(exist.password !== Number(password)){ return res.status(400).json('Invalid Credentials'); } let payload = { user : { id : exist.id } } // 给回调函数补充大括号修复语法错误 jwt.sign(payload,'jwtSecret',{expiresIn : 3600000}, (err,token)=>{ if (err) throw err; return res.json({token}) }) } catch (error) { res.status(500).json({error : error.msg}) } })
额外优化建议
当前代码存在明文存储密码的安全风险,建议做如下调整:
- 将MongoDB Schema中
password、confirmpassword的字段类型从Number改为String - 注册接口引入
bcrypt等加密库,对用户密码做加盐哈希后再存入数据库 - 登录接口使用加密库提供的比对方法校验密码,禁止明文直接比对
内容的提问来源于stack exchange,提问作者Sandeep
相关产品推荐
相关产品推荐

