Sequelize调用实例方法verifyPassword提示不是函数如何解决?
问题原因
- Sequelize版本兼容问题:你目前使用的是Sequelize v4.0.0及以上版本,该版本已经正式移除了模型配置项中的
instanceMethods、classMethods参数,旧版本的实例方法定义规则已经失效,你写的verifyPassword方法没有被挂载到模型实例上,调用时自然会报方法不存在的错误。 - 存在隐藏逻辑错误:你当前控制器中调用
verifyPassword时传入的是数据库存储的加密密码user.password,不符合校验逻辑,应该传入用户提交的明文密码req.body.password。
解决方案
步骤1:修改实例方法定义方式
删除模型配置里的instanceMethods配置块,直接把自定义方法挂载到模型的原型对象上,修改后的模型代码如下:
const {Sequelize,DataTypes} =require('sequelize') const Db =require('../config/mysql_connecton'); const bcrypt = require('bcrypt'); const User= Db.define('User', { firstName:{ type:DataTypes.STRING, allowNull:false, }, midName:{ type:DataTypes.STRING, }, lastName:{ type:DataTypes.STRING, }, email:{ type:DataTypes.STRING, allowNull:false, unique: true, validate:{ isEmail:true } }, contactNo:{ type:DataTypes.STRING, allowNull:false, unique: true }, username:{ type:DataTypes.STRING, allowNull:false, unique: true }, password:{ type:DataTypes.STRING, allowNull:false, set(value){ this.setDataValue('password',bcrypt.hashSync(value, 10)) } } }, { timestamps: true // 删除原来的instanceMethods配置 }); // 直接挂载实例方法到原型 User.prototype.verifyPassword = function(password) { return bcrypt.compareSync(password, this.password); } Db.sync() module.exports = User;
步骤2:修正控制器逻辑
补充用户不存在的判空逻辑,同时修改校验时传入的参数,修改后的控制器代码如下:
const User = require('../models/user'); module.exports.login = async (req,res)=>{ try{ //password - confirm password check at client side const user = await User.findOne({where:{username:req.body.username}}); // 先判空,避免用户不存在时调用方法报错 if(!user) { return res.sendStatus(403); } // 传入用户输入的明文密码校验 if(user.verifyPassword(req.body.password)){ console.log("密码校验通过"); return res.sendStatus(200); } // 密码校验不通过也返回403 return res.sendStatus(403); }catch(err){ console.error(`Error in logging user: ${err}`); return res.sendStatus(403); } }
如果你使用的是Sequelize v6及以上版本,也可以采用类式继承的方式定义模型和实例方法,逻辑本质和挂载原型一致。
内容的提问来源于stack exchange,提问作者AJAY BEDRE
相关产品推荐
相关产品推荐

