You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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 });
  }
},

额外注意事项

  1. 用户注册时的密码加密:确保注册接口中使用bcrypt对密码进行加密后再存入数据库,示例代码:
// 注册接口示例
const hashedPassword = await bcrypt.hash(password, 10);
const newUser = await userModel.create({ username, password: hashedPassword });
  1. JWT_SECRET配置:确保JWT_SECRET是一个安全的随机字符串,不要硬编码在代码中,建议通过环境变量配置。

内容的提问来源于stack exchange,提问作者EROS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 15:12:50