Sequelize模型authTable添加methods时提示undefined,如何解决?
解决Sequelize模型添加bcrypt方法时的"Cannot set property of undefined"错误
嘿,我来帮你搞定这个问题!你遇到的TypeError: Cannot set property 'generateHash' of undefined报错,核心原因是Sequelize的模型对象并没有methods这个属性,你直接尝试给它赋值自然会失败。下面我给你两种正确的写法,以及修复代码里的另一个小问题:
错误原因拆解
你原来的代码里直接写authTable.methods.generateHash,但authTable是Sequelize返回的模型构造函数,它本身没有methods这个属性,所以会提示"undefined"的错误。Sequelize有专门的方式来定义实例方法。
解决方案
方案1:适配Sequelize v4及以上版本(推荐)
在新版本的Sequelize中,实例方法需要直接添加到模型的prototype上:
var bcrypt = require("bcryptjs"); module.exports = function (sequelize, DataTypes) { var authTable = sequelize.define("authTable", { username: { type: DataTypes.STRING, allowNull: false, validate: { len: [1, 30] } }, password: { type: DataTypes.STRING, allowNull: false, validate: { len: [6, 20] } }, email: { type: DataTypes.STRING, allowNull: false, validate: { isEmail: true, len: [1] } } }); // 直接给模型的prototype添加实例方法 authTable.prototype.generateHash = function(password) { return bcrypt.hashSync(password, bcrypt.genSaltSync(10), null); }; authTable.prototype.validPassword = function(password) { // 注意:你的模型里密码字段是password,不是local.password,这里要修正 return bcrypt.compareSync(password, this.password); }; // 可选:添加钩子,创建用户时自动加密密码 authTable.beforeCreate(function(user) { user.password = user.generateHash(user.password); }); return authTable; }
方案2:适配Sequelize v3及更早版本
如果你用的是旧版本Sequelize,可以在define的第三个参数(配置选项)里通过instanceMethods定义方法:
var bcrypt = require("bcryptjs"); module.exports = function (sequelize, DataTypes) { var authTable = sequelize.define("authTable", { username: { type: DataTypes.STRING, allowNull: false, validate: { len: [1, 30] } }, password: { type: DataTypes.STRING, allowNull: false, validate: { len: [6, 20] } }, email: { type: DataTypes.STRING, allowNull: false, validate: { isEmail: true, len: [1] } } }, { // 旧版本通过instanceMethods定义实例方法 instanceMethods: { generateHash: function(password) { return bcrypt.hashSync(password, bcrypt.genSaltSync(10), null); }, validPassword: function(password) { return bcrypt.compareSync(password, this.password); } }, // 可选:自动加密密码的钩子 hooks: { beforeCreate: function(user) { user.password = user.generateHash(user.password); } } }); return authTable; }
额外修复点
你原来的validPassword方法里写了this.local.password,这是错误的——你的模型里并没有local这个字段,直接用this.password就能访问到用户的密码字段。
优化建议
添加beforeCreate钩子后,你在创建用户时就不需要手动调用generateHash了,Sequelize会自动在保存用户到数据库前加密密码,比如:
authTable.create({ username: "testuser", password: "mypassword123", email: "test@example.com" });
这样存入数据库的密码就是加密后的哈希值,而不是明文。
内容的提问来源于stack exchange,提问作者Jesse Adams
相关产品推荐
相关产品推荐

