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

Sequelize ^6.6.5搭配bcrypt ^5.0.1实现密码哈希时报错求助

报错根因

报错信息明确指向bcrypt.hashSync的入参不符合要求:第一个参数password必须为字符串或Buffer类型,你当前的请求中req.body.password大概率是undefined、null、数字等非合法类型。同时你未给异步方法加异常捕获逻辑,才会抛出未处理的Promise拒绝警告。


解决方案

1. 增加请求参数校验

在加密逻辑前先校验密码参数合法性,避免非法入参传入bcrypt。

2. 改用bcrypt异步API

异步API不会阻塞Node.js事件循环,更符合Node.js开发规范,配合async/await语法使用体验更好。

3. 补充异常捕获逻辑

给控制器方法增加try/catch块,捕获业务逻辑中的异常,避免未处理的Promise报错。

4. (可选)将加密逻辑下沉到模型层

使用Sequelize的beforeCreate钩子自动处理密码加密,控制器无需感知加密逻辑,代码更易维护。


修改后的代码示例

控制器代码(UserController.js)

const User = require('../models/User');
const bcrypt = require('bcrypt');

module.exports = {
  async store(req, res) {
    try {
      const { name, age, city, email, password } = req.body;
      // 新增参数校验
      if (!password || typeof password !== 'string') {
        return res.status(400).json({ error: '密码为必填参数,且必须为字符串类型' });
      }
      // 改用异步hash方法,不需要单独生成salt,直接传rounds即可
      const hash = await bcrypt.hash(password, 10);
      const user = await User.create({ name, age, city, email, password: hash });
      // 不要返回密码字段到前端
      const userWithoutPassword = user.toJSON();
      delete userWithoutPassword.password;
      return res.json(userWithoutPassword);
    } catch (err) {
      return res.status(500).json({ error: '用户创建失败', detail: err.message });
    }
  },

  async index(req, res) {
    try {
      const users = await User.findAll({
        attributes: { exclude: ['password'] } // 查询时排除密码字段
      });
      return res.json(users);
    } catch (err) {
      return res.status(500).json({ error: '用户列表查询失败', detail: err.message });
    }
  },

  async findById(req, res) {
    try {
      const { id } = req.params;
      const user = await User.findByPk(id, {
        attributes: { exclude: ['password'] }
      });
      if (!user) {
        return res.status(404).json({ error: '用户不存在' });
      }
      return res.json(user);
    } catch (err) {
      return res.status(500).json({ error: '用户查询失败', detail: err.message });
    }
  },
};

(可选)新增模型钩子后的User模型代码

如果你选择把加密逻辑放到模型层,控制器可以不用处理加密逻辑,模型代码修改如下:

const { Model, DataTypes } = require('sequelize');
const bcrypt = require('bcrypt');

class User extends Model {
  static init(sequelize) {
    super.init({
      name: DataTypes.STRING,
      age: DataTypes.INTEGER,
      city: DataTypes.STRING,
      email: DataTypes.STRING,
      password: DataTypes.STRING,
    }, {
      sequelize,
      hooks: {
        beforeCreate: async (user) => {
          if (user.password) {
            user.password = await bcrypt.hash(user.password, 10);
          }
        }
      }
    })
  }

  static associate(models) {
    this.hasMany(models.Post, { foreignKey: 'user_id', as: 'posts' });
  }
}

module.exports = User;

这个方案下控制器的store方法里不需要再手动处理密码加密,直接把原密码传给User.create即可,模型会自动完成加密。


额外验证步骤

如果修改后仍然报错,可以在加密逻辑前打印req.body和password的值,确认前端传参是否正确,是否存在拼写错误(比如前端传的是pwd而不是password)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 18:45:03