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

Node.js使用Sequelize、JWT、MySQL实现登录授权时密码一致却登录失败

代码问题梳理

1. findSalt函数错误处理逻辑异常

function findSalt (email) {
    return new Promise((resolve, reject) => {
        User.findOne({where: {email}})
            .then(result => {
                resolve(result);
            })
            .catch(err => {
                resolve(err); // 错误点:查询异常时应该reject而非resolve
            });
    })
}

如果数据库查询抛出异常,错误对象会被正常resolve,后续调用createHash(password, doc.salt)时,doc是错误对象不存在salt属性,直接抛出异常进入全局catch,返回登录失败。

2. 用户校验分支未中断Promise链,导致重复发送响应

你在判断user == null时直接调用了res.json({msg: "failed"})然后return,此时return的是undefined,Promise链会继续执行后续的then:

.then((user) => {
    if (user == null) {
        res.json({msg: "failed"}); 
        return; // 仅返回undefined,不会中断整个Promise链
    }
    // 生成token逻辑
})
.then(token => { 
    // 此时token为undefined,依然会执行这段逻辑
    const parsedKey = 'access_' + email;
    return saveRedis(req, parsedKey, token, 60 * 5);
}) 
.then((token) => { 
    // 二次调用res.json会抛出「响应头已发送」的错误
    res.cookie('accessToken', token, {secure: false, httpOnly: true,readOnly : true});
    res.json({msg: 'success'});
})
.catch(err => {
    // 上述错误会进入catch分支,再次发送响应最终返回失败
    res.json({msg: "failed", err});
});

这是密码哈希正确依旧登录失败的核心原因:第一次发送响应后,后续逻辑重复触发响应发送报错,进入全局catch。

3. 冗余Promise包装(非功能问题,可优化)

findUser和findSalt不需要手动封装Promise,Sequelize的查询方法本身就返回Promise,直接返回即可减少逻辑冗余。


修复方案

  1. 修正findSalt的catch分支,改为reject(err)
  2. 用户不存在时直接抛出错误中断Promise链:
.then((user) => {
    if (user == null) {
        throw new Error('账号或密码错误')
    }
    // 原有生成token的逻辑
})
  1. 确认saveRedis函数返回值为传入的token,避免后续写入cookie的值错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 11:45:03