首页 > 解决方案 > Sequelize:beforeCreate 挂钩不更新散列密码

问题描述

我正在尝试使用beforeCreate钩子保存散列密码。但是,我生成的散列不会保存,而是保存纯文本版本。

这就是我的UserAuth模型的样子

interface IUserAuthAttributes {
  user_auth_id: number;
  username: string;
  password: string;
  full_name: string;
  disable_user: number;
  user_level_id: number;
  created_modified: string | Date;
}

interface IUserAuthCreationAttributes
  extends Optional<IUserAuthAttributes, 'user_auth_id' | 'disable_user' | 'user_level_id' | 'created_modified'> {
  username: string;
  password: string;
  full_name: string;
}

export class UserAuth
  extends Model<IUserAuthAttributes, IUserAuthCreationAttributes>
  implements IUserAuthAttributes {
  public user_auth_id!: number;
  public username!: string;
  public password!: string;
  public full_name!: string;
  public disable_user: number;
  public user_level_id!: number;
  public created_modified: string | Date;

  public toUserJSON: () => UserAuth;
  public generateAccessToken: (payload: IUser) => string;
  public generateRefreshToken: (payload: IUser) => string;
  public passwordMatch: (pw: string, cb: (err: any, isMatch?: any) => void) => void;
  public getRole: () => 'meter_reader' | 'evaluator' | null;
}

UserAuth.init({
  user_auth_id: {
    autoIncrement: true,
    type: DataTypes.INTEGER.UNSIGNED,
    allowNull: false,
    primaryKey: true
  },
  username: {
    type: DataTypes.STRING(20),
    allowNull: false,
    defaultValue: ""
  },
  password: {
    type: DataTypes.STRING(100),
    allowNull: false,
    defaultValue: ""
  },
  full_name: {
    type: DataTypes.STRING(100),
    allowNull: false,
    defaultValue: ""
  }
  // ... other 
},
  {
    sequelize: DBInstance,
    tableName: 'user_auth',
    timestamps: false,
});

这就是我定义钩子的方式:

UserAuth.beforeCreate((user, option) => {
  const salt = bcrypt.genSaltSync();

  //  Using hashSync throws an error "Illegal arguments: undefined, string"
  // const hash = bcrypt.hashSync(user.password, salt);

  bcrypt.hash("password", salt, (err, hash) => {
    if (err) throw new Error(err.message);

    console.log('HASH -------', hash);
    user.password = hash;
  });
});

当我创建用户时:

const { username, password, full_name } = req.body;

const user = await UserAuth.create({
   username, password, full_name
});

将散列值记录到控制台后,我确实成功生成了一个

HASH ------- $2a$10$KN.OSRXR7Od8WajjuD3hyutqk1tGS/Be.V9NDrm3F7fyZWxYAbJ/2

标签: mysqlnode.jssequelize.js

解决方案


终于找到了解决办法。

在我之前的代码中,我使用回调来生成盐和哈希。同样从前面的代码 const hash = bcrypt.hashSync(user.getDataValue('password'), salt);它抛出一个错误Illegal arguments: undefined, string,因为user.password从实例返回未定义,所以相反,我使用getDataValue实例的方法获取密码的值,然后使用setDataValue设置散列密码而不是使用赋值操作user.password = hash

UserAuth.beforeCreate((user, option) => {
  if (user.isNewRecord) {
    const salt = bcrypt.genSaltSync();
    const hash = bcrypt.hashSync(user.getDataValue('password'), salt);

   // user.password = hash; Not working
    user.setDataValue('password', hash); // use this instead
  }
})

推荐阅读