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

REST API密码更新测试异常:相同密码哈希值每次不同

密码更新测试失败:相同密码生成不同哈希值导致匹配失败

我在实现REST API时遇到密码更新测试问题:即使输入相同密码,每次生成的哈希值都不一样,导致哈希匹配失败,每次运行测试都会得到新的哈希值。已经加了console.log排查,但没找到问题,相关代码如下:

user.js

const getUserById = async (userId) => {
  try {
    const user = await app.db('users').where({ id: userId }).first();
    return user;
  } catch (error) {
    throw error;
  }
};

const updatePasswordDashboard = async (data) => {
  try {
      const user = await getUserById(data.id);
      console.log('Stored Password:', user.password);
      console.log('Hashed Password from Request:', getPasswdHash(data.password));
      console.log('Password Request:', data.password);

  if(getPasswdHash(data.password) === user.password){
    if (data.newPassword === data.confirmNewPassword) {
      try {
        const newPassHash = getPasswdHash(data.newPassword);

        const updatedUser = await app.db('users')
          .returning(['password', 'first_name'])
          .where({ id: data.id })
          .update({ password: newPassHash });

        return updatedUser;
      } catch (error) {
        return error;
      }
    } else {
      throw new ValidationError('Palavras-passes nao coincidem!');
    }
  }
  else{
    throw new ValidationError('Palavra-passe errada!');
  }
} catch (error) {
  throw error;
}
 
};

users.js

router.put('/updatepassworddashboard/:id', async (req, res) => {
  try {
    console.log('Request received:', req.body);

    const result = await app.services.user.updatePasswordDashboard({
      id: req.params.id, password: req.body.password, newPassword: req.body.newPassword, confirmNewPassword: req.body.confirmNewPassword,
    });
    return res.status(200).json({ resultado: result[0], message: 'Palavra-passe alterada com sucesso' });
  } catch (err) {
    console.log(err);
    return res.status(400).json({ error: err });
  }
});

users.test.js

test('Teste 12 - Atualizar palavra passe - dashboard', () => request(app).put(`${MAIN_ROUTE}/updatepassworddashboard/${user.id}`)
.set('authorization', `bearer ${user.token}`)
.send({ password: '12345', newPassword: '1234567', confirmNewPassword: '1234567',})
.then((res) => {
  expect(res.status).toBe(200);
  expect(res.body.password).not.toBe('');
}));

问题根源

密码哈希函数(比如bcrypt这类)每次生成哈希时会自动生成随机盐值,所以直接用===比较哈希字符串是完全错误的。不同的盐值会导致相同密码生成不同的哈希结果,这是哈希算法的安全设计,目的是防止彩虹表攻击。

修复步骤

  1. 替换哈希比较逻辑:不要直接调用getPasswdHash(data.password)和存储的哈希做相等判断,改用哈希库提供的专门验证方法(比如bcrypt的bcrypt.compare())。修改后的代码示例:
    const updatePasswordDashboard = async (data) => {
      try {
        const user = await getUserById(data.id);
        console.log('Stored Password:', user.password);
        console.log('Password Request:', data.password);
    
        // 用哈希库的compare方法验证密码,而不是重新哈希后对比
        const isPasswordValid = await bcrypt.compare(data.password, user.password);
        
        if(isPasswordValid) {
          if (data.newPassword === data.confirmNewPassword) {
            const newPassHash = await bcrypt.hash(data.newPassword, 10); // 10为盐轮数,可根据需求调整
    
            const updatedUser = await app.db('users')
              .returning(['password', 'first_name'])
              .where({ id: data.id })
              .update({ password: newPassHash });
    
            return updatedUser;
          } else {
            throw new ValidationError('Palavras-passes nao coincidem!');
          }
        } else {
          throw new ValidationError('Palavra-passe errada!');
        }
      } catch (error) {
        throw error;
      }
    };
    
  2. 检查getPasswdHash实现:如果这个函数是你自己封装的,确保它使用了带随机盐的哈希算法(比如bcrypt.hash()),而不是MD5、SHA这类无盐哈希。如果是第三方库,确认它的哈希逻辑是安全的。
  3. 统一哈希调用:不要在代码中多次调用哈希函数(你之前调用了两次getPasswdHash(data.password)),既浪费性能,也可能因为盐值随机导致结果不一致,应该尽量减少不必要的哈希计算。
  4. 测试前置验证:确保测试用的用户初始密码是通过正确的哈希流程存入数据库的,比如在测试setup阶段用同样的哈希函数生成初始密码的哈希值,再插入数据库。

额外优化

  • 去掉嵌套的try-catch,外层的try已经可以捕获内部所有错误,简化代码结构。
  • 可以给哈希函数添加盐轮数配置(比如bcrypt的10),平衡安全性和性能。

内容的提问来源于stack exchange,提问作者Miguel Ângelo Freitas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 02:25:39