使用Swagger、NodeJS、JWT的登录接口凭证验证无效问题求助
问题分析与修复方案
你的登录功能无论输入什么都返回令牌,核心问题全部出在后端userController.js的逻辑错误上,以下是具体问题和修复步骤:
核心错误点
- 字段名不匹配:前端传参是
username,后端解构的是userName,导致查询条件无法正确匹配用户 - 查询逻辑完全颠倒:查到用户时反而返回"用户未找到"的错误,且异步回调和后续代码执行顺序混乱
- bcrypt密码验证无效:定义了异步验证函数但未调用,且参数顺序错误(应该用输入密码和数据库加密密码对比)
- JWT生成错误:使用模型本身
userModel而非查询到的用户实例生成令牌,导致令牌内容无效 - 混合异步写法:同时使用
async/await和then/catch,导致错误处理失效 - 安全隐患:直接用明文密码查询数据库,密码应存储加密后的哈希值
修复后的代码
前端login.js(仅修正错误提示字段)
var form = document.getElementById('login') form.addEventListener('submit', login) async function login(event) { event.preventDefault() const username = document.getElementById('username').value const password = document.getElementById('password').value const result = await fetch('/v1/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }).then((res) => res.json()) if (result.status === 'ok') { console.log('Got the token: ', result.data) localStorage.setItem('token', result.data) alert('Login Successful') return false; } else { // 后端返回的错误字段是message,修正此处 alert(result.message) } }
后端userController.js(完全重构逻辑)
login: async (req, res) => { try { // 与前端传参字段保持一致:username const { username, password } = req.body; // 仅根据用户名查询用户(密码是加密的,不能明文查询) const existUser = await userModel.findOne({ username }); // 未查到用户,返回错误 if (!existUser) { return res.status(400).json({ status: 'Failed', message: '用户不存在', data: null }); } // 验证输入密码与数据库加密密码是否匹配 const isPasswordValid = await bcrypt.compare(password, existUser.password); // 密码不匹配,返回错误 if (!isPasswordValid) { return res.status(400).json({ status: 'Failed', message: '密码错误', data: null }); } // 基于查询到的用户实例生成JWT令牌 const token = jwt.sign( { id: existUser._id, username: existUser.username }, JWT_SECRET ); // 返回成功结果与令牌 res.json({ status: 'ok', data: token }); } catch (e) { // 捕获数据库或其他异常 res.status(500).json({ status: 'Failed', message: e.message, data: null }); } },
额外注意事项
- 用户注册时的密码加密:确保注册接口中使用bcrypt对密码进行加密后再存入数据库,示例代码:
// 注册接口示例 const hashedPassword = await bcrypt.hash(password, 10); const newUser = await userModel.create({ username, password: hashedPassword });
- JWT_SECRET配置:确保
JWT_SECRET是一个安全的随机字符串,不要硬编码在代码中,建议通过环境变量配置。
内容的提问来源于stack exchange,提问作者EROS
相关产品推荐
相关产品推荐

