Sequelize实例方法不起作用

时间:2016-05-09 12:08:02

标签: node.js sequelize.js

我正在尝试使用Sequelize的实例方法来验证登录尝试时的密码。 我已将用户模型定义为:

var User = sequelize.define('User',{
    id:{
          type:DataTypes.BIGINT,
          autoIncrement: true,
          allowNull: false,
          primaryKey:true
        },
    username:{
          type:DataTypes.STRING,
          unique:true
        },
    password:{
          type: DataTypes.STRING
        },
    ...
  },
  {
    classMethods:{
        associate:function(models){
        ...
        }
      }
  },
  {
    instanceMethods:{
        validatePassword:function(password){
          return bcrypt.compareSync(password, this.password);
        }
      }
  }
);
  return User;
}

在我的登录路线中,我执行以下操作:

  • 1)检索用户名&来自请求正文的密码
  • 2)检查数据库中是否存在用户名
  • 3)如果用户存在,则使用validatePassword方法获取用户对象并将发送的密码与数据库中的散列密码进行比较。

以下是相关代码

var username = req.body.username || "";
var password = req.body.password || "";
models.User.findOne({ where: {username: username} }).
then(
    function(user) {
     if(user){
      console.log(user.validatePassword(password));
     }
 ....

每次我尝试登录时都会出现以下错误

[TypeError: user.validatePassword is not a function]

我做错了什么?

5 个答案:

答案 0 :(得分:11)

对于遇到类似问题的任何人,我都遇到了相同的问题,但使用的是Sequelize 5.21.5。根据{{​​3}},从Sequelize 4.0及更高版本开始,您必须使用原型方法来定义实例方法,如下所示:

    // Adding an instance level methods.
    User.prototype.validPassword = function(password) {
      return bcrypt.compareSync(password, this.password);
};

答案 1 :(得分:5)

我认为你正在使用sequelize模型定义api错误。 http://docs.sequelizejs.com/en/latest/docs/models-definition/#expansion-of-models

这是正确的方法:

var User = sequelize.define('User',{}, {
  classMethods: {
    method1: ...
  },
  instanceMethods: {
    method2: ...
  }
});

不喜欢这样:

var User = sequelize.define('User',{}, {
  classMethods: {
    method1: ...
  }
},{
  instanceMethods: {
    method2: ...
  }
});

答案 2 :(得分:1)

我使用这种方法:

 /**
     * Define your route model bindings, pattern filters, etc.
     *
     * @return void
     */
    public function boot()
    {
        $this->configureRateLimiting();

        $this->routes(function () {
            Route::prefix('api')
                ->middleware('api')
                ->namespace($this->namespace)
                ->group(base_path('routes/api.php'));

            Route::middleware('web')
                ->namespace($this->namespace)
                ->group(base_path('routes/web.php'));

            Route::prefix('posts')
            ->namespace($this->namespace)
            ->group(base_path('routes/api/post.php'));
        });
    }

答案 3 :(得分:0)

我们可以将instanceLevelMethods添加到原型中,

User.prototype.your-instance-level-method-name = function() {
    return 'foo';
};

我是这样做的:

// Adding an instance level methods.
User.prototype.validPassword = function(password) {
    return bcrypt.compareSync(password, this.password);
};

答案 4 :(得分:0)

如sequelize所示:“ sequelize”:如@ user1695032所示,访问实例方法的“ ^ 5.21.7”返回未定义。

这是我在console.log()中传递用户对象的几个小时未定义后从以下查询返回的结果:

User {
  dataValues: {
    id: 1,
    firtName: null,
    lasteName: null,
    email: 'ugbanawaji.ekenekiso@ust.edu.ng',
    phone: null,
    password: '$2b$10$yEWnBFMAe15RLLgyU3XlrOUyw19c4PCmh8GJe9QVz3YkbdzK5fHWu',
    createdAt: 2020-05-27T21:45:02.000Z,
    updatedAt: 2020-05-27T21:45:02.000Z
  },
  _previousDataValues: {
    id: 1,
    firtName: null,
    lasteName: null,
    email: 'ugbanawaji.ekenekiso@ust.edu.ng',
    phone: null,
    password: '$2b$10$yEWnBFMAe15RLLgyU3XlrOUyw19c4PCmh8GJe9QVz3YkbdzK5fHWu',
    createdAt: 2020-05-27T21:45:02.000Z,
    updatedAt: 2020-05-27T21:45:02.000Z
  },
  _changed: {},
  **_modelOptions: {**
    timestamps: true,
    validate: {},
    freezeTableName: false,
    underscored: false,
    paranoid: false,
    rejectOnEmpty: false,
    whereCollection: { email: 'ugbanawaji.ekenekiso@ust.edu.ng' },
    schema: null,
    schemaDelimiter: '',
    defaultScope: {},
    scopes: {},
    indexes: [],
    name: { plural: 'Users', singular: 'User' },
    omitNull: false,
    **instanceMethods: { comparePasswords: [Function: comparePasswords] },**
    hooks: { beforeValidate: [Array] },
    sequelize: Sequelize {
      options: [Object],
      config: [Object],
      dialect: [MysqlDialect],
      queryInterface: [QueryInterface],
      models: [Object],
      modelManager: [ModelManager],
      connectionManager: [ConnectionManager],
      importCache: [Object]
    }
  },
  _options: {
    isNewRecord: false,
    _schema: null,
    _schemaDelimiter: '',
    raw: true,
    attributes: [
      'id',        'firtName',
      'lasteName', 'email',
      'phone',     'password',
      'createdAt', 'updatedAt'
    ]
  },
  isNewRecord: false
}

错误前的代码:

 models.User.findOne({where: {email: req.body.email}}).then((user)=>{
            console.log(user)
            if(!user) {
                res.status(401).json({ message: 'Authentication failed!' });
                } else {
                user.comparePasswords(req.body.password, (error, isMatch) =>{
                    console.log(error + ' -- ' + isMatch)
                    if(isMatch && !error) {
                        const token = jwt.sign(
                            { username: user.username },
                            keys.secret,
                            { expiresIn: '30h' }
                        );

                        res.status(200).json({ success: true,message: 'signed in successfully', token: 'JWT ' + token });
                    } else {
                        res.status(401).json({ success: false, message: 'Login failed!' });
                    }
                });
            }
        }).catch((error)=>{
            console.log(error)
            res.status(500).json({ success: false, message: 'There was an error!'});
        })

这会导致 TypeError:user.comparePasswords不是函数

更改此行后:

** user.comparePasswords(req.body.password, (error, isMatch) =>{} **

对此:

** user._modelOptions.instanceMethods.comparePasswords(req.body.password, (error, isMatch) =>{}**

嘘!一切正常