Sequelize: beforeCreate 挂钩不更新散列密码

Sequelize: beforeCreate hook not updating hashed password

我正在尝试使用 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 ------- a$KN.OSRXR7Od8WajjuD3hyutqk1tGS/Be.V9NDrm3F7fyZWxYAbJ/2

终于找到解决办法了。

在我之前的代码中,我使用回调来生成盐和哈希。同样来自之前的代码 const hash = bcrypt.hashSync(user.getDataValue('password'), salt); 它抛出错误 Illegal arguments: undefined, string 因为 user.password returns 未在实例中定义,所以我使用 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
  }
})